Merge "Refactor Geocoder Provider System APIs" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 2846221..b89a51a 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -32,6 +32,7 @@
     ":android.credentials.flags-aconfig-java{.generated_srcjars}",
     ":android.database.sqlite-aconfig-java{.generated_srcjars}",
     ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
+    ":android.hardware.devicestate.feature.flags-aconfig-java{.generated_srcjars}",
     ":android.hardware.flags-aconfig-java{.generated_srcjars}",
     ":android.hardware.radio.flags-aconfig-java{.generated_srcjars}",
     ":android.hardware.usb.flags-aconfig-java{.generated_srcjars}",
@@ -108,6 +109,7 @@
         "android.credentials.flags-aconfig",
         "android.database.sqlite-aconfig",
         "android.hardware.biometrics.flags-aconfig",
+        "android.hardware.devicestate.feature.flags-aconfig",
         "android.hardware.flags-aconfig",
         "android.hardware.radio.flags-aconfig",
         "android.hardware.usb.flags-aconfig",
@@ -227,6 +229,19 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// DeviceStateManager
+aconfig_declarations {
+    name: "android.hardware.devicestate.feature.flags-aconfig",
+    package: "android.hardware.devicestate.feature.flags",
+    srcs: ["core/java/android/hardware/devicestate/feature/*.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.hardware.devicestate.feature.flags-aconfig-java",
+    aconfig_declarations: "android.hardware.devicestate.feature.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Input
 aconfig_declarations {
     name: "com.android.hardware.input.input-aconfig",
diff --git a/Android.bp b/Android.bp
index e12f74f..870df5a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -508,6 +508,8 @@
     lint: {
         baseline_filename: "lint-baseline.xml",
     },
+    // For jarjar repackaging
+    jarjar_prefix: "com.android.internal.hidden_from_bootclasspath",
 }
 
 java_library {
diff --git a/core/api/current.txt b/core/api/current.txt
index ec8699a..5aa10e9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -144,10 +144,12 @@
     field public static final String MANAGE_DEVICE_POLICY_AUDIO_OUTPUT = "android.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT";
     field public static final String MANAGE_DEVICE_POLICY_AUTOFILL = "android.permission.MANAGE_DEVICE_POLICY_AUTOFILL";
     field public static final String MANAGE_DEVICE_POLICY_BACKUP_SERVICE = "android.permission.MANAGE_DEVICE_POLICY_BACKUP_SERVICE";
+    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL = "android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL";
     field public static final String MANAGE_DEVICE_POLICY_BLUETOOTH = "android.permission.MANAGE_DEVICE_POLICY_BLUETOOTH";
     field public static final String MANAGE_DEVICE_POLICY_BUGREPORT = "android.permission.MANAGE_DEVICE_POLICY_BUGREPORT";
     field public static final String MANAGE_DEVICE_POLICY_CALLS = "android.permission.MANAGE_DEVICE_POLICY_CALLS";
     field public static final String MANAGE_DEVICE_POLICY_CAMERA = "android.permission.MANAGE_DEVICE_POLICY_CAMERA";
+    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE";
     field public static final String MANAGE_DEVICE_POLICY_CERTIFICATES = "android.permission.MANAGE_DEVICE_POLICY_CERTIFICATES";
     field public static final String MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE = "android.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE";
     field @FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled") public static final String MANAGE_DEVICE_POLICY_CONTENT_PROTECTION = "android.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION";
@@ -169,6 +171,7 @@
     field @FlaggedApi("android.app.admin.flags.esim_management_enabled") public static final String MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS = "android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS";
     field public static final String MANAGE_DEVICE_POLICY_METERED_DATA = "android.permission.MANAGE_DEVICE_POLICY_METERED_DATA";
     field public static final String MANAGE_DEVICE_POLICY_MICROPHONE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE";
+    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE";
     field public static final String MANAGE_DEVICE_POLICY_MOBILE_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK";
     field public static final String MANAGE_DEVICE_POLICY_MODIFY_USERS = "android.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS";
     field public static final String MANAGE_DEVICE_POLICY_MTE = "android.permission.MANAGE_DEVICE_POLICY_MTE";
@@ -454,6 +457,7 @@
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
     field public static final int allowClickWhenDisabled = 16844312; // 0x1010618
+    field @FlaggedApi("android.security.asm_restrictions_enabled") public static final int allowCrossUidActivitySwitchFromBelow;
     field public static final int allowEmbedded = 16843765; // 0x10103f5
     field public static final int allowGameAngleDriver = 16844376; // 0x1010658
     field public static final int allowGameDownscaling = 16844377; // 0x1010659
@@ -687,6 +691,7 @@
     field public static final int defaultHeight = 16844021; // 0x10104f5
     field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale;
     field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
+    field @FlaggedApi("android.nfc.Flags.FLAG_OBSERVE_MODE") public static final int defaultToObserveMode;
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -1491,6 +1496,7 @@
     field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261
     field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d
     field public static final int shell = 16844180; // 0x1010594
+    field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang;
     field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
     field public static final int shortcutId = 16844072; // 0x1010528
     field public static final int shortcutLongLabel = 16844074; // 0x101052a
@@ -5459,11 +5465,15 @@
     method public int getDeferralPolicy();
     method @Nullable public String getDeliveryGroupMatchingKey();
     method public int getDeliveryGroupPolicy();
+    method @FlaggedApi("android.app.bcast_event_timestamps") public long getEventTriggerTimestampMillis();
+    method @FlaggedApi("android.app.bcast_event_timestamps") public long getRemoteEventTriggerTimestampMillis();
     method public boolean isShareIdentityEnabled();
     method @NonNull public static android.app.BroadcastOptions makeBasic();
     method @NonNull public android.app.BroadcastOptions setDeferralPolicy(int);
     method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
     method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
+    method @FlaggedApi("android.app.bcast_event_timestamps") public void setEventTriggerTimestampMillis(long);
+    method @FlaggedApi("android.app.bcast_event_timestamps") public void setRemoteEventTriggerTimestampMillis(long);
     method @NonNull public android.app.BroadcastOptions setShareIdentityEnabled(boolean);
     method @NonNull public android.os.Bundle toBundle();
     field public static final int DEFERRAL_POLICY_DEFAULT = 0; // 0x0
@@ -8113,6 +8123,7 @@
     method public boolean isLogoutEnabled();
     method public boolean isManagedProfile(@NonNull android.content.ComponentName);
     method public boolean isMasterVolumeMuted(@NonNull android.content.ComponentName);
+    method @FlaggedApi("android.app.admin.flags.is_mte_policy_enforced") public static boolean isMtePolicyEnforced();
     method public boolean isNetworkLoggingEnabled(@Nullable android.content.ComponentName);
     method public boolean isOrganizationOwnedDeviceWithManagedProfile();
     method public boolean isOverrideApnEnabled(@NonNull android.content.ComponentName);
@@ -20002,11 +20013,14 @@
 
   public final class ExtensionSessionConfiguration {
     ctor public ExtensionSessionConfiguration(int, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraExtensionSession.StateCallback);
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public void clearColorSpace();
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") @Nullable public android.graphics.ColorSpace getColorSpace();
     method @NonNull public java.util.concurrent.Executor getExecutor();
     method public int getExtension();
     method @NonNull public java.util.List<android.hardware.camera2.params.OutputConfiguration> getOutputConfigurations();
     method @Nullable public android.hardware.camera2.params.OutputConfiguration getPostviewOutputConfiguration();
     method @NonNull public android.hardware.camera2.CameraExtensionSession.StateCallback getStateCallback();
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public void setColorSpace(@NonNull android.graphics.ColorSpace.Named);
     method public void setPostviewOutputConfiguration(@Nullable android.hardware.camera2.params.OutputConfiguration);
   }
 
@@ -22731,7 +22745,6 @@
 
   public final class MediaCodec.QueueRequest {
     method public void queue();
-    method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setBufferInfos(@NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
     method @NonNull public android.media.MediaCodec.QueueRequest setByteBufferParameter(@NonNull String, @NonNull java.nio.ByteBuffer);
     method @NonNull public android.media.MediaCodec.QueueRequest setEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int, @NonNull android.media.MediaCodec.CryptoInfo);
     method @NonNull public android.media.MediaCodec.QueueRequest setFlags(int);
@@ -22741,6 +22754,7 @@
     method @NonNull public android.media.MediaCodec.QueueRequest setLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int);
     method @NonNull public android.media.MediaCodec.QueueRequest setLongParameter(@NonNull String, long);
     method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>);
+    method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
     method @NonNull public android.media.MediaCodec.QueueRequest setPresentationTimeUs(long);
     method @NonNull public android.media.MediaCodec.QueueRequest setStringParameter(@NonNull String, @NonNull String);
   }
@@ -22749,12 +22763,16 @@
     method @NonNull public String getCanonicalName();
     method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(String);
     method @NonNull public String getName();
+    method @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public int getSecurityModel();
     method public String[] getSupportedTypes();
     method public boolean isAlias();
     method public boolean isEncoder();
     method public boolean isHardwareAccelerated();
     method public boolean isSoftwareOnly();
     method public boolean isVendor();
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_MEMORY_SAFE = 1; // 0x1
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_SANDBOXED = 0; // 0x0
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; // 0x2
   }
 
   public static final class MediaCodecInfo.AudioCapabilities {
@@ -23583,6 +23601,9 @@
     field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
     field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
     field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = 2; // 0x2
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_SANDBOXED = 1; // 0x1
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 4; // 0x4
     field public static final String KEY_AAC_DRC_ALBUM_MODE = "aac-drc-album-mode";
     field public static final String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
     field public static final String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
@@ -23664,6 +23685,7 @@
     field public static final String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
     field public static final String KEY_ROTATION = "rotation-degrees";
     field public static final String KEY_SAMPLE_RATE = "sample-rate";
+    field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final String KEY_SECURITY_MODEL = "security-model";
     field public static final String KEY_SLICE_HEIGHT = "slice-height";
     field public static final String KEY_SLOW_MOTION_MARKERS = "slow-motion-markers";
     field public static final String KEY_STRIDE = "stride";
@@ -42390,6 +42412,7 @@
     field public static final int SUPPORTS_SET_INACTIVE = 2; // 0x2
     field public static final int SUPPORTS_STREAM = 4; // 0x4
     field public static final int SUPPORTS_TRANSFER = 8; // 0x8
+    field @FlaggedApi("com.android.server.telecom.flags.transactional_video_state") public static final int SUPPORTS_VIDEO_CALLING = 16; // 0x10
     field public static final int VIDEO_CALL = 2; // 0x2
   }
 
@@ -42425,6 +42448,7 @@
     method @NonNull public android.os.ParcelUuid getCallId();
     method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method @FlaggedApi("com.android.server.telecom.flags.set_mute_state") public void requestMuteState(boolean, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
+    method @FlaggedApi("com.android.server.telecom.flags.transactional_video_state") public void requestVideoState(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void sendEvent(@NonNull String, @NonNull android.os.Bundle);
     method public void setActive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void setInactive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -42473,6 +42497,7 @@
     method public void onCallStreamingFailed(int);
     method public void onEvent(@NonNull String, @NonNull android.os.Bundle);
     method public void onMuteStateChanged(boolean);
+    method @FlaggedApi("com.android.server.telecom.flags.transactional_video_state") public default void onVideoStateChanged(int);
   }
 
   public final class CallException extends java.lang.RuntimeException implements android.os.Parcelable {
@@ -47526,6 +47551,7 @@
     method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public android.text.DynamicLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
     method @NonNull public android.text.DynamicLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
     method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.DynamicLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.DynamicLayout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
     method @NonNull public android.text.DynamicLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.DynamicLayout.Builder setUseBoundsForWidth(boolean);
     method @NonNull public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean);
@@ -47729,6 +47755,7 @@
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @Nullable public final int[] getRightIndents();
     method public float getSecondaryHorizontal(int);
     method public void getSelectionPath(int, int, android.graphics.Path);
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public boolean getShiftDrawingOffsetForStartOverhang();
     method public final float getSpacingAdd();
     method public final float getSpacingMultiplier();
     method @NonNull public final CharSequence getText();
@@ -47785,6 +47812,7 @@
     method @NonNull public android.text.Layout.Builder setMaxLines(@IntRange(from=1) int);
     method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.Layout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
     method @NonNull public android.text.Layout.Builder setRightIndents(@Nullable int[]);
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.Layout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
     method @NonNull public android.text.Layout.Builder setTextDirectionHeuristic(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.Layout.Builder setUseBoundsForWidth(boolean);
   }
@@ -48056,6 +48084,7 @@
     method @NonNull public android.text.StaticLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
     method @NonNull public android.text.StaticLayout.Builder setMaxLines(@IntRange(from=0) int);
     method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.StaticLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.StaticLayout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
     method public android.text.StaticLayout.Builder setText(CharSequence);
     method @NonNull public android.text.StaticLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.StaticLayout.Builder setUseBoundsForWidth(boolean);
@@ -50565,7 +50594,6 @@
     method public default void removeOnBufferTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnBufferTransformHintChangedListener);
     method public default void setChildBoundingInsets(@NonNull android.graphics.Rect);
     method public default void setTouchableRegion(@Nullable android.graphics.Region);
-    method @FlaggedApi("com.android.window.flags.transfer_gesture_to_embedded") public default boolean transferHostTouchGestureToEmbedded(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
   }
 
   @UiThread public static interface AttachedSurfaceControl.OnBufferTransformHintChangedListener {
@@ -52283,6 +52311,7 @@
   public static final class SurfaceControlViewHost.SurfacePackage implements android.os.Parcelable {
     ctor public SurfaceControlViewHost.SurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
     method public int describeContents();
+    method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") @Nullable public android.window.InputTransferToken getInputTransferToken();
     method @NonNull public android.view.SurfaceControl getSurfaceControl();
     method public void notifyConfigurationChanged(@NonNull android.content.res.Configuration);
     method public void notifyDetachedFromWindow();
@@ -53243,7 +53272,7 @@
     field protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
     field protected static final int[] PRESSED_STATE_SET;
     field protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
-    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = 0.0f;
+    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = (0.0f/0.0f);
     field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4.0f;
     field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2.0f;
     field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3.0f;
@@ -54425,8 +54454,10 @@
     method public default void removeProposedRotationListener(@NonNull java.util.function.IntConsumer);
     method @FlaggedApi("com.android.window.flags.screen_recording_callbacks") @RequiresPermission(android.Manifest.permission.DETECT_SCREEN_RECORDING) public default void removeScreenRecordingCallback(@NonNull java.util.function.Consumer<java.lang.Integer>);
     method public void removeViewImmediate(android.view.View);
+    method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") public default boolean transferTouchGesture(@NonNull android.window.InputTransferToken, @NonNull android.window.InputTransferToken);
     method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") public default void unregisterSurfaceControlInputReceiver(@NonNull android.view.SurfaceControl);
     method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public default void unregisterTrustedPresentationListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
+    field @FlaggedApi("com.android.window.flags.cover_display_opt_in") public static final int COMPAT_SMALL_COVER_SCREEN_OPT_IN = 1; // 0x1
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED = "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
     field @FlaggedApi("com.android.window.flags.untrusted_embedding_state_sharing") public static final String PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING = "android.window.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING";
@@ -54439,6 +54470,7 @@
     field public static final String PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE";
     field @FlaggedApi("com.android.window.flags.app_compat_properties_api") public static final String PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES = "android.window.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES";
     field public static final String PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS = "android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS";
+    field @FlaggedApi("com.android.window.flags.cover_display_opt_in") public static final String PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN = "android.window.PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN";
     field @FlaggedApi("com.android.window.flags.app_compat_properties_api") public static final String PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE";
     field @FlaggedApi("com.android.window.flags.app_compat_properties_api") public static final String PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE";
     field public static final String PROPERTY_COMPAT_ENABLE_FAKE_FOCUS = "android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS";
@@ -60872,6 +60904,7 @@
     method public float getShadowDx();
     method public float getShadowDy();
     method public float getShadowRadius();
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public boolean getShiftDrawingOffsetForStartOverhang();
     method public final boolean getShowSoftInputOnFocus();
     method public CharSequence getText();
     method @NonNull public android.view.textclassifier.TextClassifier getTextClassifier();
@@ -61008,6 +61041,7 @@
     method public void setSearchResultHighlights(@Nullable int...);
     method public void setSelectAllOnFocus(boolean);
     method public void setShadowLayer(float, float, float, int);
+    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public void setShiftDrawingOffsetForStartOverhang(boolean);
     method public final void setShowSoftInputOnFocus(boolean);
     method public void setSingleLine();
     method public void setSingleLine(boolean);
diff --git a/core/api/lint-baseline.txt b/core/api/lint-baseline.txt
index 9b8ab9b..1b0da05 100644
--- a/core/api/lint-baseline.txt
+++ b/core/api/lint-baseline.txt
@@ -1461,6 +1461,7 @@
     New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getItalicOverride(int)
 UnflaggedApi: android.graphics.text.PositionedGlyphs#getWeightOverride(int):
     New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getWeightOverride(int)
+
 UnflaggedApi: android.hardware.camera2.ExtensionCaptureRequest:
     New API must be flagged with @FlaggedApi: class android.hardware.camera2.ExtensionCaptureRequest
 UnflaggedApi: android.hardware.camera2.ExtensionCaptureRequest#ExtensionCaptureRequest():
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 20a621ba..8fe3876 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -195,6 +195,7 @@
     field public static final String MANAGE_DEFAULT_APPLICATIONS = "android.permission.MANAGE_DEFAULT_APPLICATIONS";
     field public static final String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final String MANAGE_DEVICE_POLICY_APP_EXEMPTIONS = "android.permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS";
+    field @FlaggedApi("android.app.admin.flags.device_theft_api_enabled") public static final String MANAGE_DEVICE_POLICY_THEFT_DETECTION = "android.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION";
     field @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public static final String MANAGE_ENHANCED_CONFIRMATION_STATES = "android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES";
     field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS";
     field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
@@ -203,7 +204,6 @@
     field public static final String MANAGE_HOTWORD_DETECTION = "android.permission.MANAGE_HOTWORD_DETECTION";
     field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final String MANAGE_LOW_POWER_STANDBY = "android.permission.MANAGE_LOW_POWER_STANDBY";
-    field @FlaggedApi("com.android.media.flags.limit_manage_media_projection") public static final String MANAGE_MEDIA_PROJECTION = "android.permission.MANAGE_MEDIA_PROJECTION";
     field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION";
     field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS";
     field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
@@ -594,6 +594,7 @@
     field public static final int FOREGROUND_SERVICE_API_TYPE_MICROPHONE = 6; // 0x6
     field public static final int FOREGROUND_SERVICE_API_TYPE_PHONE_CALL = 7; // 0x7
     field public static final int FOREGROUND_SERVICE_API_TYPE_USB = 8; // 0x8
+    field @FlaggedApi("android.media.audio.foreground_audio_control") public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 64; // 0x40
     field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
     field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
@@ -1322,6 +1323,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean isDpcDownloaded();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isManagedKiosk();
     method public boolean isSecondaryLockscreenEnabled(@NonNull android.os.UserHandle);
+    method @FlaggedApi("android.app.admin.flags.device_theft_api_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION) public boolean isTheftDetectionTriggered();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isUnattendedManagedKiosk();
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long);
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
@@ -4756,9 +4758,13 @@
 
   @FlaggedApi("com.android.internal.camera.flags.concert_mode") public final class CameraOutputSurface {
     ctor @FlaggedApi("com.android.internal.camera.flags.concert_mode") public CameraOutputSurface(@NonNull android.view.Surface, @NonNull android.util.Size);
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public int getColorSpace();
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public long getDynamicRangeProfile();
     method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public int getImageFormat();
     method @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public android.util.Size getSize();
     method @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public android.view.Surface getSurface();
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public void setColorSpace(int);
+    method @FlaggedApi("com.android.internal.camera.flags.extension_10_bit") public void setDynamicRangeProfile(long);
   }
 
   @FlaggedApi("com.android.internal.camera.flags.concert_mode") public class CharacteristicsMap {
@@ -4835,6 +4841,39 @@
 
 }
 
+package android.hardware.devicestate {
+
+  @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
+    method @IntRange(from=0x0) public int getIdentifier();
+    method @NonNull public String getName();
+    method public boolean hasProperties(@NonNull int...);
+    method public boolean hasProperty(int);
+    field public static final int PROPERTY_EMULATED_ONLY = 10; // 0xa
+    field public static final int PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY = 15; // 0xf
+    field public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17; // 0x11
+    field public static final int PROPERTY_FEATURE_REAR_DISPLAY = 16; // 0x10
+    field public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY = 12; // 0xc
+    field public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY = 11; // 0xb
+    field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED = 1; // 0x1
+    field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN = 2; // 0x2
+    field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN = 3; // 0x3
+    field public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP = 13; // 0xd
+    field public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE = 14; // 0xe
+  }
+
+  @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceStateManager {
+    method @NonNull public java.util.List<android.hardware.devicestate.DeviceState> getSupportedDeviceStates();
+    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+    method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+  }
+
+  public static interface DeviceStateManager.DeviceStateCallback {
+    method public default void onDeviceStateChanged(@NonNull android.hardware.devicestate.DeviceState);
+    method public default void onSupportedStatesChanged(@NonNull java.util.List<android.hardware.devicestate.DeviceState>);
+  }
+
+}
+
 package android.hardware.display {
 
   public final class AmbientBrightnessDayStats implements android.os.Parcelable {
@@ -10239,6 +10278,7 @@
     ctor @FlaggedApi("android.nfc.enable_nfc_mainline") public ApduServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo, boolean) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilter(@NonNull String);
     method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void addPollingLoopFilterToAutoTransact(@NonNull String);
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean defaultToObserveMode();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public int describeContents();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dump(@NonNull android.os.ParcelFileDescriptor, @NonNull java.io.PrintWriter, @NonNull String[]);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void dumpDebug(@NonNull android.util.proto.ProtoOutputStream);
@@ -10268,6 +10308,7 @@
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresUnlock();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setCategoryOtherServiceEnabled(boolean);
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public void setDefaultToObserveMode(boolean);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -14351,9 +14392,9 @@
 
   @FlaggedApi("com.android.internal.telephony.flags.use_oem_domain_selection_service") public abstract class DomainSelectionService extends android.app.Service {
     ctor public DomainSelectionService();
+    method @NonNull public java.util.concurrent.Executor getCreateExecutor();
     method public void onBarringInfoUpdated(int, int, @NonNull android.telephony.BarringInfo);
     method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
-    method @NonNull public java.util.concurrent.Executor onCreateExecutor();
     method public abstract void onDomainSelection(@NonNull android.telephony.DomainSelectionService.SelectionAttributes, @NonNull android.telephony.TransportSelectorCallback);
     method public void onServiceStateUpdated(int, int, @NonNull android.telephony.ServiceState);
     field public static final int SCAN_TYPE_FULL_SERVICE = 2; // 0x2
@@ -15133,6 +15174,7 @@
     method @Deprecated public boolean getDataEnabled(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion(int);
+    method @FlaggedApi("android.permission.flags.get_emergency_role_holder_api_enabled") @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getEmergencyAssistancePackage();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index a6505c8..ca9fab8 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -535,6 +535,10 @@
     Listeners should always be at end of argument list (method `stopSatelliteTransmissionUpdates`)
 
 
+MethodNameUnits: android.hardware.camera2.extension.CameraOutputSurface#getColorSpace():
+    Expected method name units to be `Bytes`, was `Space` in `getColorSpace`
+
+
 MissingGetterMatchingBuilder: android.service.voice.HotwordTrainingData.Builder#addTrainingAudio(android.service.voice.HotwordTrainingAudio):
     android.service.voice.HotwordTrainingData does not declare a `getTrainingAudios()` method matching method android.service.voice.HotwordTrainingData.Builder.addTrainingAudio(android.service.voice.HotwordTrainingAudio)
 MissingGetterMatchingBuilder: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallViaAudioProcessing(boolean):
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f6366a2..334d9e6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1620,22 +1620,26 @@
 
 package android.hardware.devicestate {
 
-  public final class DeviceStateManager {
+  @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
+    ctor @Deprecated public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, int);
+    ctor public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, @NonNull java.util.Set<java.lang.Integer>);
+    field public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8; // 0x8
+  }
+
+  @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceStateManager {
     method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void cancelBaseStateOverride();
     method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelStateRequest();
-    method @NonNull public int[] getSupportedStates();
-    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+    method @Deprecated @NonNull public int[] getSupportedStates();
     method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void requestBaseStateOverride(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
     method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
-    method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
-    field public static final int MAXIMUM_DEVICE_STATE = 255; // 0xff
-    field public static final int MINIMUM_DEVICE_STATE = 0; // 0x0
+    field public static final int MAXIMUM_DEVICE_STATE_IDENTIFIER = 10000; // 0x2710
+    field public static final int MINIMUM_DEVICE_STATE_IDENTIFIER = 0; // 0x0
   }
 
   public static interface DeviceStateManager.DeviceStateCallback {
-    method public default void onBaseStateChanged(int);
-    method public void onStateChanged(int);
-    method public default void onSupportedStatesChanged(@NonNull int[]);
+    method @Deprecated public default void onBaseStateChanged(int);
+    method @Deprecated public void onStateChanged(int);
+    method @Deprecated public default void onSupportedStatesChanged(@NonNull int[]);
   }
 
   public final class DeviceStateRequest {
diff --git a/core/java/android/adaptiveauth/flags.aconfig b/core/java/android/adaptiveauth/flags.aconfig
index 39e46bb..de4e607 100644
--- a/core/java/android/adaptiveauth/flags.aconfig
+++ b/core/java/android/adaptiveauth/flags.aconfig
@@ -1,6 +1,13 @@
 package: "android.adaptiveauth"
 
 flag {
+  name: "enable_adaptive_auth"
+  namespace: "biometrics"
+  description: "Feature flag for enabling the new adaptive auth service"
+  bug: "285053096"
+}
+
+flag {
   name: "report_biometric_auth_attempts"
   namespace: "biometrics"
   description: "Control the usage of the biometric auth signal in adaptive auth"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a8d183a..237d31c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.windowingModeToString;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.media.audio.Flags.FLAG_FOREGROUND_AUDIO_CONTROL;
 
 import android.Manifest;
 import android.annotation.ColorInt;
@@ -794,6 +795,7 @@
             PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
             PROCESS_CAPABILITY_BFSL,
             PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK,
+            PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProcessCapability {}
@@ -943,6 +945,14 @@
     public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 1 << 5;
 
     /**
+     * @hide
+     * Process can access volume APIs and can request audio focus with GAIN.
+     */
+    @FlaggedApi(FLAG_FOREGROUND_AUDIO_CONTROL)
+    @SystemApi
+    public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 1 << 6;
+
+    /**
      * @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
      *
      * Don't expose it as TestApi -- we may add new capabilities any time, which could
@@ -953,7 +963,8 @@
             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
             | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
             | PROCESS_CAPABILITY_BFSL
-            | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
+            | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK
+            | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
 
     /**
      * All implicit capabilities. There are capabilities that process automatically have.
@@ -975,6 +986,7 @@
         pw.print((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
         pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
         pw.print((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
     }
 
     /** @hide */
@@ -986,6 +998,7 @@
         sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
         sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
         sb.append((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
     }
 
     /**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index e14bf68..2a2c5f0 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
 import static android.view.Display.INVALID_DISPLAY;
@@ -1849,7 +1850,7 @@
     public int getPendingIntentLaunchFlags() {
         // b/243794108: Ignore all flags except the new task flag, to be reconsidered in b/254490217
         return mPendingIntentLaunchFlags &
-                (FLAG_ACTIVITY_NEW_TASK | FLAG_RECEIVER_FOREGROUND);
+                (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK | FLAG_RECEIVER_FOREGROUND);
     }
 
     /**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2100425..409badb 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,7 +16,9 @@
 
 package android.app;
 
+
 import static android.location.flags.Flags.FLAG_LOCATION_BYPASS;
+import static android.media.audio.Flags.foregroundAudioControl;
 import static android.permission.flags.Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER;
 import static android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED;
 import static android.view.contentprotection.flags.Flags.FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED;
@@ -3229,6 +3231,10 @@
      * @hide
      */
     public static @Mode int opToDefaultMode(int op) {
+        if (op == OP_TAKE_AUDIO_FOCUS && foregroundAudioControl()) {
+            // when removing the flag, change the entry in sAppOpInfos for OP_TAKE_AUDIO_FOCUS
+            return AppOpsManager.MODE_FOREGROUND;
+        }
         return sAppOpInfos[op].defaultMode;
     }
 
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index f727ee5..1b5b0fc 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -65,6 +67,8 @@
     private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
     private @Nullable IntentFilter mDeliveryGroupMatchingFilter;
     private @DeferralPolicy int mDeferralPolicy;
+    private @CurrentTimeMillisLong long mEventTriggerTimestampMillis;
+    private @CurrentTimeMillisLong long mRemoteEventTriggerTimestampMillis;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
@@ -190,6 +194,18 @@
             "android:broadcast.idForResponseEvent";
 
     /**
+     * Corresponds to {@link #setEventTriggerTimestampMillis(long)}.
+     */
+    private static final String KEY_EVENT_TRIGGER_TIMESTAMP =
+            "android:broadcast.eventTriggerTimestamp";
+
+    /**
+     * Corresponds to {@link #setRemoteEventTriggerTimestampMillis(long)}.
+     */
+    private static final String KEY_REMOTE_EVENT_TRIGGER_TIMESTAMP =
+            "android:broadcast.remoteEventTriggerTimestamp";
+
+    /**
      * Corresponds to {@link #setDeliveryGroupPolicy(int)}.
      */
     private static final String KEY_DELIVERY_GROUP_POLICY =
@@ -341,6 +357,8 @@
         mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
         mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
         mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
+        mEventTriggerTimestampMillis = opts.getLong(KEY_EVENT_TRIGGER_TIMESTAMP);
+        mRemoteEventTriggerTimestampMillis = opts.getLong(KEY_REMOTE_EVENT_TRIGGER_TIMESTAMP);
         mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
                 DELIVERY_GROUP_POLICY_ALL);
         mDeliveryGroupMatchingNamespaceFragment = opts.getString(KEY_DELIVERY_GROUP_NAMESPACE);
@@ -787,6 +805,60 @@
     }
 
     /**
+     * Set the timestamp for the event that triggered this broadcast, in
+     * {@link System#currentTimeMillis()} timebase.
+     *
+     * <p> For instance, if this broadcast is for a push message, then this timestamp
+     * could correspond to when the device received the message.
+     *
+     * @param timestampMillis the timestamp in {@link System#currentTimeMillis()} timebase that
+     *                        correspond to the event that triggered this broadcast.
+     */
+    @FlaggedApi(android.app.Flags.FLAG_BCAST_EVENT_TIMESTAMPS)
+    public void setEventTriggerTimestampMillis(@CurrentTimeMillisLong long timestampMillis) {
+        mEventTriggerTimestampMillis = timestampMillis;
+    }
+
+    /**
+     * Return the timestamp for the event that triggered this broadcast, in
+     * {@link System#currentTimeMillis()} timebase.
+     *
+     * @return the timestamp in {@link System#currentTimeMillis()} timebase that was previously
+     *         set using {@link #setEventTriggerTimestampMillis(long)}.
+     */
+    @FlaggedApi(android.app.Flags.FLAG_BCAST_EVENT_TIMESTAMPS)
+    public @CurrentTimeMillisLong long getEventTriggerTimestampMillis() {
+        return mEventTriggerTimestampMillis;
+    }
+
+    /**
+     * Set the timestamp for the remote event, if any, that triggered this broadcast, in
+     * {@link System#currentTimeMillis()} timebase.
+     *
+     * <p> For instance, if this broadcast is for a push message, then this timestamp
+     * could correspond to when the message originated remotely.
+     *
+     * @param timestampMillis the timestamp in {@link System#currentTimeMillis()} timebase that
+     *                        correspond to the remote event that triggered this broadcast.
+     */
+    @FlaggedApi(android.app.Flags.FLAG_BCAST_EVENT_TIMESTAMPS)
+    public void setRemoteEventTriggerTimestampMillis(@CurrentTimeMillisLong long timestampMillis) {
+        mRemoteEventTriggerTimestampMillis = timestampMillis;
+    }
+
+    /**
+     * Return the timestamp for the remote event that triggered this broadcast, in
+     * {@link System#currentTimeMillis()} timebase.
+     *
+     * @return the timestamp in {@link System#currentTimeMillis()} timebase that was previously
+     *         set using {@link #setRemoteEventTriggerTimestampMillis(long)}}.
+     */
+    @FlaggedApi(android.app.Flags.FLAG_BCAST_EVENT_TIMESTAMPS)
+    public @CurrentTimeMillisLong long getRemoteEventTriggerTimestampMillis() {
+        return mRemoteEventTriggerTimestampMillis;
+    }
+
+    /**
      * Sets deferral policy for this broadcast that specifies how this broadcast
      * can be deferred for delivery at some future point.
      */
@@ -1120,6 +1192,12 @@
         if (mIdForResponseEvent != 0) {
             b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
         }
+        if (mEventTriggerTimestampMillis > 0) {
+            b.putLong(KEY_EVENT_TRIGGER_TIMESTAMP, mEventTriggerTimestampMillis);
+        }
+        if (mRemoteEventTriggerTimestampMillis > 0) {
+            b.putLong(KEY_REMOTE_EVENT_TRIGGER_TIMESTAMP, mRemoteEventTriggerTimestampMillis);
+        }
         if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
             b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
         }
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index f92ff83..da0cc01 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -31,6 +31,7 @@
 per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS
 per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS
 per-file *UiAutomation* = file:/services/accessibility/OWNERS
+per-file *UiAutomation* = file:/core/java/android/permission/OWNERS
 per-file GameManager* = file:/GAME_MANAGER_OWNERS
 per-file GameMode* = file:/GAME_MANAGER_OWNERS
 per-file GameState* = file:/GAME_MANAGER_OWNERS
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index ff23f09..350b1ed 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -34,3 +34,10 @@
      description: "Add a new callback in Service to indicate a FGS has reached its timeout."
      bug: "317799821"
 }
+
+flag {
+    name: "bcast_event_timestamps"
+    namespace: "backstage_power"
+    description: "Add APIs for clients to provide broadcast event trigger timestamps"
+    bug: "325136414"
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 34fb754..367ade0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -45,6 +45,7 @@
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
@@ -55,6 +56,7 @@
 import static android.app.admin.flags.Flags.FLAG_ESIM_MANAGEMENT_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED;
 import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
+import static android.app.admin.flags.Flags.FLAG_IS_MTE_POLICY_ENFORCED;
 import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
@@ -153,6 +155,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.internal.os.Zygote;
 
 import java.io.ByteArrayInputStream;
 import java.io.FileNotFoundException;
@@ -4117,6 +4120,19 @@
         return MTE_NOT_CONTROLLED_BY_POLICY;
     }
 
+    /**
+     * Get the current MTE state of the device.
+     *
+     * <a href="https://source.android.com/docs/security/test/memory-safety/arm-mte">
+     * Learn more about MTE</a>
+     *
+     * @return whether MTE is currently enabled on the device.
+     */
+    @FlaggedApi(FLAG_IS_MTE_POLICY_ENFORCED)
+    public static boolean isMtePolicyEnforced() {
+        return Zygote.nativeSupportsMemoryTagging();
+    }
+
     /** Indicates that content protection is not controlled by policy, allowing user to choose. */
     @FlaggedApi(android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED)
     public static final int CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY = 0;
@@ -17044,6 +17060,26 @@
     }
 
     /**
+     *
+     * Returns whether the device considers itself to be potentially stolen.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_THEFT_DETECTION)
+    @FlaggedApi(Flags.FLAG_DEVICE_THEFT_API_ENABLED)
+    public boolean isTheftDetectionTriggered() {
+        throwIfParentInstance("isTheftDetectionTriggered");
+        if (mService == null) {
+            return false;
+        }
+        try {
+            return mService.isTheftDetectionTriggered(mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns a {@link DevicePolicyResourcesManager} containing the required APIs to set, reset,
      * and get device policy related resources.
      */
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f2466ac..ca4a5ab 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -576,6 +576,8 @@
     void setWifiSsidPolicy(String callerPackageName, in WifiSsidPolicy policy);
     WifiSsidPolicy getWifiSsidPolicy(String callerPackageName);
 
+    boolean isTheftDetectionTriggered(String callerPackageName);
+
     List<UserHandle> listForegroundAffiliatedUsers();
     void setDrawables(in List<DevicePolicyDrawableResource> drawables);
     void resetDrawables(in List<String> drawableIds);
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 726ddad..cbd8e5b 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -139,3 +139,10 @@
   description: "Add Headless DO support."
   bug: "289515470"
 }
+
+flag {
+  name: "is_mte_policy_enforced"
+  namespace: "enterprise"
+  description: "Allow to query whether MTE is enabled or not to check for compliance for enterprise policy"
+  bug: "322777918"
+}
diff --git a/core/java/android/app/ondeviceintelligence/OWNERS b/core/java/android/app/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..6932ba2
--- /dev/null
+++ b/core/java/android/app/ondeviceintelligence/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 1363385
+
+sandeepbandaru@google.com
+shivanker@google.com
+hackz@google.com
+volnov@google.com
+
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index a8dba51..cae4fab 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1565,6 +1565,14 @@
     private Boolean requestRawExternalStorageAccess;
 
     /**
+     * If {@code false}, this app does not allow its activities to be replaced by another app.
+     * Is set from application manifest application tag's allowCrossUidActivitySwitchFromBelow
+     * attribute.
+     * @hide
+     */
+    public boolean allowCrossUidActivitySwitchFromBelow = true;
+
+    /**
      * Represents the default policy. The actual policy used will depend on other properties of
      * the application, e.g. the target SDK version.
      * @hide
@@ -1760,6 +1768,9 @@
                         + Integer.toHexString(localeConfigRes));
             }
             pw.println(prefix + "enableOnBackInvokedCallback=" + isOnBackInvokedCallbackEnabled());
+            pw.println(prefix + "allowCrossUidActivitySwitchFromBelow="
+                    + allowCrossUidActivitySwitchFromBelow);
+
         }
         pw.println(prefix + "createTimestamp=" + createTimestamp);
         if (mKnownActivityEmbeddingCerts != null) {
@@ -1877,6 +1888,8 @@
                 proto.write(ApplicationInfoProto.Detail.NATIVE_HEAP_ZERO_INIT,
                         nativeHeapZeroInitialized);
             }
+            proto.write(ApplicationInfoProto.Detail.ALLOW_CROSS_UID_ACTIVITY_SWITCH_FROM_BELOW,
+                    allowCrossUidActivitySwitchFromBelow);
             proto.end(detailToken);
         }
         if (!ArrayUtils.isEmpty(mKnownActivityEmbeddingCerts)) {
@@ -2002,6 +2015,7 @@
         nativeHeapZeroInitialized = orig.nativeHeapZeroInitialized;
         requestRawExternalStorageAccess = orig.requestRawExternalStorageAccess;
         localeConfigRes = orig.localeConfigRes;
+        allowCrossUidActivitySwitchFromBelow = orig.allowCrossUidActivitySwitchFromBelow;
         createTimestamp = SystemClock.uptimeMillis();
     }
 
@@ -2106,6 +2120,8 @@
             }
         }
         dest.writeInt(localeConfigRes);
+        dest.writeInt(allowCrossUidActivitySwitchFromBelow ? 1 : 0);
+
         sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags);
     }
 
@@ -2204,6 +2220,8 @@
             }
         }
         localeConfigRes = source.readInt();
+        allowCrossUidActivitySwitchFromBelow = source.readInt() != 0;
+
         mKnownActivityEmbeddingCerts = sForStringSet.unparcel(source);
         if (mKnownActivityEmbeddingCerts.isEmpty()) {
             mKnownActivityEmbeddingCerts = null;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 49c8a7c..2a67353 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2554,6 +2554,15 @@
     public static final int INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST = -130;
 
     /**
+     * Installation failed return code: if the system failed to install the package that
+     * {@link android.R.attr#multiArch} is true in its manifest because its packaged
+     * native code did not match all of the natively ABIs supported by the system.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS = -131;
+
+    /**
      * App minimum aspect ratio set by the user which will override app-defined aspect ratio.
      *
      * @hide
@@ -10452,6 +10461,8 @@
             case INSTALL_FAILED_SESSION_INVALID: return "INSTALL_FAILED_SESSION_INVALID";
             case INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST:
                 return "INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST";
+            case INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS:
+                return "INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS";
             default: return Integer.toString(status);
         }
     }
diff --git a/core/java/android/hardware/camera2/extension/CameraOutputSurface.java b/core/java/android/hardware/camera2/extension/CameraOutputSurface.java
index b4fe7fe..53f56bc 100644
--- a/core/java/android/hardware/camera2/extension/CameraOutputSurface.java
+++ b/core/java/android/hardware/camera2/extension/CameraOutputSurface.java
@@ -18,8 +18,11 @@
 
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.graphics.ImageFormat;
+import android.hardware.camera2.params.ColorSpaceProfiles;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.camera2.utils.SurfaceUtils;
 import android.util.Size;
 import android.view.Surface;
@@ -65,6 +68,8 @@
         mOutputSurface.size = new android.hardware.camera2.extension.Size();
         mOutputSurface.size.width = size.getWidth();
         mOutputSurface.size.height = size.getHeight();
+        mOutputSurface.dynamicRangeProfile = DynamicRangeProfiles.STANDARD;
+        mOutputSurface.colorSpace = ColorSpaceProfiles.UNSPECIFIED;
     }
 
     /**
@@ -95,4 +100,48 @@
     public @ImageFormat.Format int getImageFormat() {
         return mOutputSurface.imageFormat;
     }
+
+    /**
+     * Return the dynamic range profile. The default
+     * dynamicRangeProfile is
+     * {@link android.hardware.camera2.params.DynamicRangeProfiles.STANDARD}
+     * unless specified by CameraOutputSurface.setDynamicRangeProfile.
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public @DynamicRangeProfiles.Profile long getDynamicRangeProfile() {
+        return mOutputSurface.dynamicRangeProfile;
+    }
+
+    /**
+     * Return the color space. The default colorSpace is
+     * {@link android.hardware.camera2.params.ColorSpaceProfiles.UNSPECIFIED}
+     * unless specified by CameraOutputSurface.setColorSpace.
+     */
+    @SuppressLint("MethodNameUnits")
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public int getColorSpace() {
+        return mOutputSurface.colorSpace;
+    }
+
+    /**
+     * Set the dynamic range profile. The default dynamicRangeProfile
+     * will be {@link android.hardware.camera2.params.DynamicRangeProfiles.STANDARD}
+     * unless explicitly set using this method.
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public void setDynamicRangeProfile(
+            @DynamicRangeProfiles.Profile long dynamicRangeProfile) {
+        mOutputSurface.dynamicRangeProfile = dynamicRangeProfile;
+    }
+
+    /**
+     * Set the color space. The default colorSpace
+     * will be
+     * {@link android.hardware.camera2.params.ColorSpaceProfiles.UNSPECIFIED}
+     * unless explicitly set using this method.
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public void setColorSpace(int colorSpace) {
+        mOutputSurface.colorSpace = colorSpace;
+    }
 }
diff --git a/core/java/android/hardware/camera2/extension/OutputSurface.aidl b/core/java/android/hardware/camera2/extension/OutputSurface.aidl
index 8415379..02e160c 100644
--- a/core/java/android/hardware/camera2/extension/OutputSurface.aidl
+++ b/core/java/android/hardware/camera2/extension/OutputSurface.aidl
@@ -24,4 +24,6 @@
     Surface surface;
     Size size;
     int imageFormat;
+    long dynamicRangeProfile;
+    int colorSpace;
 }
diff --git a/core/java/android/hardware/camera2/params/ExtensionSessionConfiguration.java b/core/java/android/hardware/camera2/params/ExtensionSessionConfiguration.java
index 0e6c1b3..69a6e9b 100644
--- a/core/java/android/hardware/camera2/params/ExtensionSessionConfiguration.java
+++ b/core/java/android/hardware/camera2/params/ExtensionSessionConfiguration.java
@@ -15,15 +15,20 @@
  */
 package android.hardware.camera2.params;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-
+import android.annotation.SuppressLint;
+import android.graphics.ColorSpace;
+import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraExtensionCharacteristics.Extension;
 import android.hardware.camera2.CameraExtensionSession;
 
 import java.util.List;
 import java.util.concurrent.Executor;
 
+import com.android.internal.camera.flags.Flags;
+
 /**
  * A class that aggregates all supported arguments for
  * {@link CameraExtensionSession} initialization.
@@ -36,6 +41,7 @@
     private OutputConfiguration mPostviewOutput = null;
     private Executor mExecutor = null;
     private CameraExtensionSession.StateCallback mCallback = null;
+    private int mColorSpace;
 
     /**
      * Create a new ExtensionSessionConfiguration
@@ -118,4 +124,55 @@
     Executor getExecutor() {
         return mExecutor;
     }
+
+    /**
+     * Set a specific device-supported color space.
+     *
+     * <p>Clients can choose from any profile advertised as supported in
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}
+     * queried using {@link ColorSpaceProfiles#getSupportedColorSpaces}.
+     * When set, the colorSpace will override the default color spaces of the output targets,
+     * or the color space implied by the dataSpace passed into an {@link ImageReader}'s
+     * constructor.</p>
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public void setColorSpace(@NonNull ColorSpace.Named colorSpace) {
+        mColorSpace = colorSpace.ordinal();
+        for (OutputConfiguration outputConfiguration : mOutputs) {
+            outputConfiguration.setColorSpace(colorSpace);
+        }
+        if (mPostviewOutput != null) {
+            mPostviewOutput.setColorSpace(colorSpace);
+        }
+    }
+
+    /**
+     * Clear the color space, such that the default color space will be used.
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    public void clearColorSpace() {
+        mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
+        for (OutputConfiguration outputConfiguration : mOutputs) {
+            outputConfiguration.clearColorSpace();
+        }
+        if (mPostviewOutput != null) {
+            mPostviewOutput.clearColorSpace();
+        }
+    }
+
+    /**
+     * Return the current color space.
+     *
+     * @return the currently set color space, or null
+     *         if not set
+     */
+    @FlaggedApi(Flags.FLAG_EXTENSION_10_BIT)
+    @SuppressLint("MethodNameUnits")
+    public @Nullable ColorSpace getColorSpace() {
+        if (mColorSpace != ColorSpaceProfiles.UNSPECIFIED) {
+            return ColorSpace.get(ColorSpace.Named.values()[mColorSpace]);
+        } else {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index 5a34905..8629354 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -16,18 +16,25 @@
 
 package android.hardware.devicestate;
 
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Collections;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * A state of the device defined by the {@link DeviceStateProvider} and managed by the
@@ -37,21 +44,29 @@
  * state of the system. This is useful for variable-state devices, like foldable or rollable
  * devices, that can be configured by users into differing hardware states, which each may have a
  * different expected use case.
- * @hide
  *
+ * @hide
  * @see DeviceStateManager
  */
+@SystemApi
+@FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
 public final class DeviceState {
     /**
      * Flag that indicates override requests should be cancelled when this device state becomes the
      * base device state.
+     * @hide
+     * @deprecated use {@link #PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS}
      */
+    @Deprecated
     public static final int FLAG_CANCEL_OVERRIDE_REQUESTS = 1 << 0;
 
     /**
      * Flag that indicates this device state is inaccessible for applications to be placed in. This
-     * could be a device-state where the {@link DEFAULT_DISPLAY} is not enabled.
+     * could be a device-state where the {@link Display#DEFAULT_DISPLAY} is not enabled.
+     * @hide
+     * @deprecated use {@link #PROPERTY_APP_INACCESSIBLE}
      */
+    @Deprecated
     public static final int FLAG_APP_INACCESSIBLE = 1 << 1;
 
     /**
@@ -60,7 +75,10 @@
      * through emulation and have no physical configuration to match.
      *
      * This flag indicates that the corresponding state can only be entered through emulation.
+     * @hide
+     * @deprecated use {@link #PROPERTY_EMULATED_ONLY}
      */
+    @Deprecated
     public static final int FLAG_EMULATED_ONLY = 1 << 2;
 
     /**
@@ -68,19 +86,28 @@
      * requesting app is no longer on top. The app is considered not on top when (1) the top
      * activity in the system is from a different app, (2) the device is in sleep mode, or
      * (3) the keyguard shows up.
+     * @hide
+     * @deprecated use {@link #PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP}
      */
+    @Deprecated
     public static final int FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 1 << 3;
 
     /**
      * This flag indicates that the corresponding state should be disabled when the device is
      * overheating and reaching the critical status.
+     * @hide
+     * @deprecated use {@link #PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL}
      */
+    @Deprecated
     public static final int FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL = 1 << 4;
 
     /**
      * This flag indicates that the corresponding state should be disabled when power save mode
      * is enabled.
+     * @hide
+     * @deprecated use {@link #PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE}
      */
+    @Deprecated
     public static final int FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE = 1 << 5;
 
     /** @hide */
@@ -92,11 +119,157 @@
             FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
             FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE
     })
+    @Deprecated
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeviceStateFlags {}
 
+    /**
+     * Property that indicates that a fold-in style foldable device is currently in a fully closed
+     * configuration.
+     */
+    public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED = 1;
+
+    /**
+     * Property that indicates that a fold-in style foldable device is currently in a half-opened
+     * configuration. This signifies that the device's hinge is positioned somewhere around 90
+     * degrees. Checking for display configuration properties as well can provide information
+     * on which display is currently active.
+     */
+    public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN = 2;
+
+    /**
+     * Property that indicates that a fold-in style foldable device is currently in a fully open
+     * configuration.
+     */
+    public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN = 3;
+
+    /**
+     * Property that indicates override requests should be cancelled when the device is physically
+     * put into this state.
+     * @hide
+     */
+    public static final int PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS = 4;
+
+    /**
+     * This property indicates that the corresponding state should be automatically canceled when
+     * the requesting app is no longer on top. The app is considered not on top when (1) the top
+     * activity in the system is from a different app, (2) the device is in sleep mode, or
+     * (3) the keyguard shows up.
+     * @hide
+     */
+    public static final int PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 5;
+
+    /**
+     * This property indicates that the corresponding state should be disabled when the device is
+     * overheating and reaching the critical status.
+     * @hide
+     */
+    public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL = 6;
+
+    /**
+     * This property indicates that the corresponding state should be disabled when power save mode
+     * is enabled.
+     * @hide
+     */
+    public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE = 7;
+
+    /**
+     * This property denotes that this state is available for applications to request and the system
+     * server should deny any request that comes from a process that does not hold the
+     * CONTROL_DEVICE_STATE permission if it is requesting a state that does not have this property
+     * on it.
+     * @hide
+     */
+    @TestApi
+    public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8;
+
+    /**
+     * Property that indicates this device state is inaccessible for applications to be made
+     * visible to the user. This could be a device-state where the {@link Display#DEFAULT_DISPLAY}
+     * is not enabled.
+     * @hide
+     */
+    public static final int PROPERTY_APP_INACCESSIBLE = 9;
+
+    /**
+     * This property indidcates that this state can only be entered through emulation and has no
+     * physical configuration to match.
+     */
+    public static final int PROPERTY_EMULATED_ONLY = 10;
+
+    /**
+     * Property that indicates that the outer display area of a foldable device is currently the
+     * primary display area.
+     *
+     * Note: This does not necessarily mean that the outer display area is the
+     * @link Display#DEFAULT_DISPLAY}.
+     */
+    public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY = 11;
+
+    /**
+     * Property that indicates that the inner display area of a foldable device is currently the
+     * primary display area.
+     *
+     * Note: This does not necessarily mean that the inner display area is the
+     * {@link Display#DEFAULT_DISPLAY}.
+     */
+    public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY = 12;
+
+    /**
+     * Property that indicates that this device state will attempt to trigger the device to go to
+     * sleep.
+     */
+    public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP = 13;
+
+    /**
+     * Property that indicates that this device state will attempt to trigger the device to wake up.
+     */
+    public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE = 14;
+
+    /**
+     * Property that indicates that an external display has been connected to the device. Specifics
+     * around display mode or properties around the display should be gathered through
+     * {@link android.hardware.display.DisplayManager}
+     */
+    public static final int PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY = 15;
+    /**
+     * Property that indicates that this state corresponds to the device state for rear display
+     * mode. This means that the active display is facing the same direction as the rear camera.
+     */
+    public static final int PROPERTY_FEATURE_REAR_DISPLAY = 16;
+
+    /**
+     * Property that indicates that this state corresponds to the device state where both displays
+     * on a foldable are active, with the internal display being the default display.
+     */
+    public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17;
+
+    /** @hide */
+    @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
+            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
+            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
+            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN,
+            PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+            PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+            PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+            PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+            PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
+            PROPERTY_APP_INACCESSIBLE,
+            PROPERTY_EMULATED_ONLY,
+            PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
+            PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+            PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
+            PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
+            PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
+            PROPERTY_FEATURE_REAR_DISPLAY,
+            PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+    public @interface DeviceStateProperties {}
+
     /** Unique identifier for the device state. */
-    @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE)
+    @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
     private final int mIdentifier;
 
     /** String description of the device state. */
@@ -106,20 +279,49 @@
     @DeviceStateFlags
     private final int mFlags;
 
+    private final Set<@DeviceStateProperties Integer> mProperties;
+
+    /**
+     * @deprecated Deprecated in favor of {@link #DeviceState(int, String, Set)}
+     * @hide
+     */
+    // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+    @TestApi
+    @Deprecated
     public DeviceState(
-            @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+            @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                    MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
             @NonNull String name,
             @DeviceStateFlags int flags) {
-        Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE, MAXIMUM_DEVICE_STATE,
+        Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
+                MAXIMUM_DEVICE_STATE_IDENTIFIER,
                 "identifier");
 
         mIdentifier = identifier;
         mName = name;
         mFlags = flags;
+        mProperties = Collections.emptySet();
+    }
+
+    /** @hide */
+    @TestApi
+    public DeviceState(
+            @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                    MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
+            @NonNull String name,
+            @NonNull Set<@DeviceStateProperties Integer> properties) {
+        Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
+                MAXIMUM_DEVICE_STATE_IDENTIFIER,
+                "identifier");
+
+        mIdentifier = identifier;
+        mName = name;
+        mProperties = Set.copyOf(properties);
+        mFlags = 0;
     }
 
     /** Returns the unique identifier for the device state. */
-    @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE)
+    @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER)
     public int getIdentifier() {
         return mIdentifier;
     }
@@ -130,6 +332,12 @@
         return mName;
     }
 
+    /**
+     * @hide
+     * @deprecated in favor of {@link #hasProperty(int)} method
+     */
+    // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+    @Deprecated
     @DeviceStateFlags
     public int getFlags() {
         return mFlags;
@@ -138,9 +346,9 @@
     @Override
     public String toString() {
         return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\''
-                + ", app_accessible=" + !hasFlag(FLAG_APP_INACCESSIBLE)
+                + ", app_accessible=" + !hasProperty(PROPERTY_APP_INACCESSIBLE)
                 + ", cancel_when_requester_not_on_top="
-                + hasFlag(FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+                + hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
                 + "}";
     }
 
@@ -151,17 +359,40 @@
         DeviceState that = (DeviceState) o;
         return mIdentifier == that.mIdentifier
                 && Objects.equals(mName, that.mName)
-                && mFlags == that.mFlags;
+                && Objects.equals(mProperties, that.mProperties);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mIdentifier, mName, mFlags);
+        return Objects.hash(mIdentifier, mName, mProperties);
     }
 
     /** Checks if a specific flag is set
+     * @hide
+     * @deprecated in favor of {@link #hasProperty(int)}
      */
+    // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+    @Deprecated
     public boolean hasFlag(int flagToCheckFor) {
         return (mFlags & flagToCheckFor) == flagToCheckFor;
     }
+
+    /**
+     * Checks if a specific property is set on this state
+     */
+    public boolean hasProperty(@DeviceStateProperties int propertyToCheckFor) {
+        return mProperties.contains(propertyToCheckFor);
+    }
+
+    /**
+     * Checks if a list of properties are all set on this state
+     */
+    public boolean hasProperties(@NonNull @DeviceStateProperties int... properties) {
+        for (int i = 0; i < properties.length; i++) {
+            if (mProperties.contains(properties[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 6a667fe..8b4d43e 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -18,15 +18,19 @@
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -36,7 +40,8 @@
  *
  * @hide
  */
-@TestApi
+@SystemApi
+@FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
 @SystemService(Context.DEVICE_STATE_SERVICE)
 public final class DeviceStateManager {
     /**
@@ -46,11 +51,19 @@
      */
     public static final int INVALID_DEVICE_STATE = -1;
 
-    /** The minimum allowed device state identifier. */
-    public static final int MINIMUM_DEVICE_STATE = 0;
+    /**
+     * The minimum allowed device state identifier.
+     * @hide
+     */
+    @TestApi
+    public static final int MINIMUM_DEVICE_STATE_IDENTIFIER = 0;
 
-    /** The maximum allowed device state identifier. */
-    public static final int MAXIMUM_DEVICE_STATE = 255;
+    /**
+     * The maximum allowed device state identifier.
+     * @hide
+     */
+    @TestApi
+    public static final int MAXIMUM_DEVICE_STATE_IDENTIFIER = 10000;
 
     /**
      * Intent needed to launch the rear display overlay activity from SysUI
@@ -83,13 +96,27 @@
     /**
      * Returns the list of device states that are supported and can be requested with
      * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+     * @deprecated use {@link #getSupportedDeviceStates()}
+     * @hide
      */
+    // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+    @TestApi
+    @Deprecated
     @NonNull
     public int[] getSupportedStates() {
         return mGlobal.getSupportedStates();
     }
 
     /**
+     * Returns the list of device states that are supported and can be requested with
+     * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+     */
+    @NonNull
+    public List<DeviceState> getSupportedDeviceStates() {
+        return mGlobal.getSupportedDeviceStates();
+    }
+
+    /**
      * Submits a {@link DeviceStateRequest request} to modify the device state.
      * <p>
      * By default, the request is kept active until one of the following occurs:
@@ -107,7 +134,10 @@
      * the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
      *
      * @see DeviceStateRequest
+     * @hide
      */
+    @SuppressLint("RequiresPermission") // Lint doesn't handle conditional permission checks today
+    @TestApi
     @RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
             conditional = true)
     public void requestState(@NonNull DeviceStateRequest request,
@@ -124,7 +154,10 @@
      *
      * @throws SecurityException if the caller is neither the current top-focused activity nor if
      * the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
+     * @hide
      */
+    @SuppressLint("RequiresPermission") // Lint doesn't handle conditional permission checks today
+    @TestApi
     @RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
             conditional = true)
     public void cancelStateRequest() {
@@ -151,11 +184,11 @@
      * emulated override requests take priority.
      *
      * @throws IllegalArgumentException if the requested state is unsupported.
-     * @throws SecurityException if the caller does not hold the
-     * {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission.
      *
      * @see DeviceStateRequest
+     * @hide
      */
+    @TestApi
     @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
     public void requestBaseStateOverride(@NonNull DeviceStateRequest request,
             @Nullable @CallbackExecutor Executor executor,
@@ -169,9 +202,9 @@
      * <p>
      * This method is noop if there is no base state request currently active.
      *
-     * @throws SecurityException if the caller does not hold the
-     * {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission.
+     * @hide
      */
+    @TestApi
     @RequiresPermission(Manifest.permission.CONTROL_DEVICE_STATE)
     public void cancelBaseStateOverride() {
         mGlobal.cancelBaseStateOverride();
@@ -209,10 +242,31 @@
          * @param supportedStates the new supported states.
          *
          * @see DeviceStateManager#getSupportedStates()
+         * @deprecated use {@link #onSupportedStatesChanged(List)}
+         * @hide
          */
+        // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+        @TestApi
+        @Deprecated
         default void onSupportedStatesChanged(@NonNull int[] supportedStates) {}
 
         /**
+         * Called in response to a change in the states supported by the device.
+         * <p>
+         * Guaranteed to be called once on registration of the callback with the initial value and
+         * then on every subsequent change in the supported states.
+         *
+         * The supported device states may change due to certain states becoming unavailable
+         * due to device configuration or device conditions such as if the device is too hot or
+         * external monitors have been connected.
+         *
+         * @param supportedStates the new supported states.
+         *
+         * @see DeviceStateManager#getSupportedDeviceStates()
+         */
+        default void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) {}
+
+        /**
          * Called in response to a change in the base device state.
          * <p>
          * The base state is the state of the device without considering any requests made through
@@ -224,7 +278,13 @@
          * then on every subsequent change in the non-override state.
          *
          * @param state the new base device state.
+         * @deprecated use {@link #onDeviceStateChanged(DeviceState)} and query for physical
+         * properties that are relevant to your needs.
+         * @hide
          */
+        // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+        @TestApi
+        @Deprecated
         default void onBaseStateChanged(int state) {}
 
         /**
@@ -234,8 +294,24 @@
          * then on every subsequent change in device state.
          *
          * @param state the new device state.
+         * @deprecated use {@link #onDeviceStateChanged(DeviceState)}
+         * @hide
          */
+        // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+        @TestApi
+        @Deprecated
         void onStateChanged(int state);
+
+        /**
+         * Called in response to device state changes.
+         * <p>
+         * Guaranteed to be called once on registration of the callback with the initial value and
+         * then on every subsequent change in device state.
+         *
+         * @param state the new device state.
+         */
+        // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+        default void onDeviceStateChanged(@NonNull DeviceState state) {}
     }
 
     /**
@@ -247,6 +323,7 @@
     public static class FoldStateListener implements DeviceStateCallback {
         private final int[] mFoldedDeviceStates;
         private final Consumer<Boolean> mDelegate;
+        private final android.hardware.devicestate.feature.flags.FeatureFlags mFeatureFlags;
 
         @Nullable
         private Boolean lastResult;
@@ -259,11 +336,23 @@
             mFoldedDeviceStates = context.getResources().getIntArray(
                     com.android.internal.R.array.config_foldedDeviceStates);
             mDelegate = listener;
+            mFeatureFlags = new android.hardware.devicestate.feature.flags.FeatureFlagsImpl();
         }
 
         @Override
-        public final void onStateChanged(int state) {
-            final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
+        public final void onStateChanged(int state) {}
+
+        @Override
+        public final void onDeviceStateChanged(@NonNull DeviceState deviceState) {
+            final boolean folded;
+            if (mFeatureFlags.deviceStatePropertyApi()) {
+                // TODO(b/325124054): Update when system server refactor is completed
+                folded = deviceState.hasProperty(
+                        DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)
+                        || ArrayUtils.contains(mFoldedDeviceStates, deviceState.getIdentifier());
+            } else {
+                folded = ArrayUtils.contains(mFoldedDeviceStates, deviceState.getIdentifier());
+            }
 
             if (lastResult == null || !lastResult.equals(folded)) {
                 lastResult = folded;
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index c379188..6db5aee 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
 import android.os.Binder;
@@ -32,9 +33,13 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -50,12 +55,18 @@
     private static final String TAG = "DeviceStateManagerGlobal";
     private static final boolean DEBUG = Build.IS_DEBUGGABLE;
 
+    // TODO(b/325124054): Remove when system server refactor is completed
+    private static int[] sFoldedDeviceStates = new int[0];
+
     /**
      * Returns an instance of {@link DeviceStateManagerGlobal}. May return {@code null} if a
      * connection with the device state service couldn't be established.
      */
     @Nullable
     public static DeviceStateManagerGlobal getInstance() {
+        // TODO(b/325124054): Remove when system server refactor is completed
+        instantiateFoldedStateArray();
+
         synchronized (DeviceStateManagerGlobal.class) {
             if (sInstance == null) {
                 IBinder b = ServiceManager.getService(Context.DEVICE_STATE_SERVICE);
@@ -68,6 +79,16 @@
         }
     }
 
+    // TODO(b/325124054): Remove when system server refactor is completed
+    // TODO(b/325330654): Investigate if we need a Context passed in to DSMGlobal
+    private static void instantiateFoldedStateArray() {
+        Context context = ActivityThread.currentApplication();
+        if (context != null) {
+            sFoldedDeviceStates = context.getResources().getIntArray(
+                    com.android.internal.R.array.config_foldedDeviceStates);
+        }
+    }
+
     private final Object mLock = new Object();
     @NonNull
     private final IDeviceStateManager mDeviceStateManager;
@@ -116,6 +137,32 @@
     }
 
     /**
+     * Returns the {@link List} of supported device states.
+     *
+     * @see DeviceStateManager#getSupportedDeviceStates()
+     */
+    public List<DeviceState> getSupportedDeviceStates() {
+        synchronized (mLock) {
+            final DeviceStateInfo currentInfo;
+            if (mLastReceivedInfo != null) {
+                // If we have mLastReceivedInfo a callback is registered for this instance and it
+                // is receiving the most recent info from the server. Use that info here.
+                currentInfo = mLastReceivedInfo;
+            } else {
+                // If mLastReceivedInfo is null there is no registered callback so we manually
+                // fetch the current info.
+                try {
+                    currentInfo = mDeviceStateManager.getDeviceStateInfo();
+                } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
+                }
+            }
+
+            return createDeviceStateList(currentInfo.supportedStates);
+        }
+    }
+
+    /**
      * Submits a {@link DeviceStateRequest request} to modify the device state.
      *
      * @see DeviceStateManager#requestState(DeviceStateRequest, Executor,
@@ -241,8 +288,10 @@
                 final int[] supportedStates = Arrays.copyOf(mLastReceivedInfo.supportedStates,
                         mLastReceivedInfo.supportedStates.length);
                 wrapper.notifySupportedStatesChanged(supportedStates);
+                wrapper.notifySupportedDeviceStatesChanged(createDeviceStateList(supportedStates));
                 wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState);
                 wrapper.notifyStateChanged(mLastReceivedInfo.currentState);
+                wrapper.notifyDeviceStateChanged(createDeviceState(mLastReceivedInfo.currentState));
             }
         }
     }
@@ -327,6 +376,8 @@
                 final int[] supportedStates = Arrays.copyOf(info.supportedStates,
                         info.supportedStates.length);
                 callbacks.get(i).notifySupportedStatesChanged(supportedStates);
+                callbacks.get(i).notifySupportedDeviceStatesChanged(
+                        createDeviceStateList(supportedStates));
             }
         }
         if ((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0) {
@@ -337,6 +388,7 @@
         if ((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0) {
             for (int i = 0; i < callbacks.size(); i++) {
                 callbacks.get(i).notifyStateChanged(info.currentState);
+                callbacks.get(i).notifyDeviceStateChanged(createDeviceState(info.currentState));
             }
         }
     }
@@ -369,6 +421,36 @@
         }
     }
 
+    /**
+     * Creates a {@link DeviceState} object from a device state identifier, with the
+     * {@link DeviceState} property that corresponds to what display is primary.
+     *
+     */
+    // TODO(b/325124054): Remove when system server refactor is completed
+    @NonNull
+    private DeviceState createDeviceState(int stateIdentifier) {
+        final Set<@DeviceState.DeviceStateProperties Integer> properties = new HashSet<>();
+        if (ArrayUtils.contains(sFoldedDeviceStates, stateIdentifier)) {
+            properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
+        } else {
+            properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY);
+        }
+        return new DeviceState(stateIdentifier, "" /* name */, properties);
+    }
+
+    /**
+     * Creates a list of {@link DeviceState} objects from an array of state identifiers.
+     */
+    // TODO(b/325124054): Remove when system server refactor is completed
+    @NonNull
+    private List<DeviceState> createDeviceStateList(int[] supportedStates) {
+        List<DeviceState> deviceStateList = new ArrayList<>();
+        for (int i = 0; i < supportedStates.length; i++) {
+            deviceStateList.add(createDeviceState(supportedStates[i]));
+        }
+        return deviceStateList;
+    }
+
     private final class DeviceStateManagerCallback extends IDeviceStateManagerCallback.Stub {
         @Override
         public void onDeviceStateInfoChanged(DeviceStateInfo info) {
@@ -403,6 +485,11 @@
                     mDeviceStateCallback.onSupportedStatesChanged(newSupportedStates));
         }
 
+        void notifySupportedDeviceStatesChanged(List<DeviceState> newSupportedDeviceStates) {
+            mExecutor.execute(() ->
+                    mDeviceStateCallback.onSupportedStatesChanged(newSupportedDeviceStates));
+        }
+
         void notifyBaseStateChanged(int newBaseState) {
             execute("notifyBaseStateChanged",
                     () -> mDeviceStateCallback.onBaseStateChanged(newBaseState));
@@ -413,6 +500,11 @@
                     () -> mDeviceStateCallback.onStateChanged(newDeviceState));
         }
 
+        void notifyDeviceStateChanged(DeviceState newDeviceState) {
+            execute("notifyDeviceStateChanged",
+                    () -> mDeviceStateCallback.onDeviceStateChanged(newDeviceState));
+        }
+
         private void execute(String traceName, Runnable r) {
             mExecutor.execute(() -> {
                 if (DEBUG) {
diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig
new file mode 100644
index 0000000..73a9e34
--- /dev/null
+++ b/core/java/android/hardware/devicestate/feature/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.hardware.devicestate.feature.flags"
+
+flag {
+    name: "device_state_property_api"
+    namespace: "windowing_sdk"
+    description: "Updated DeviceState hasProperty API"
+    bug: "293636629"
+    is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index e8c8b5a..9218cb8 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -111,3 +111,22 @@
     description: "When the flag is off no permissions can be device aware"
     bug: "274852670"
 }
+
+flag {
+     name: "get_emergency_role_holder_api_enabled"
+     is_fixed_read_only: true
+     namespace: "permissions"
+     description: "Enables the getEmergencyRoleHolder API."
+     bug: "323157319"
+}
+
+flag {
+    name: "new_permission_gid_enabled"
+    is_fixed_read_only: true
+    namespace: "permissions"
+    description: "Enable new permission GID implementation"
+    bug: "325137277"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/core/java/android/service/ondeviceintelligence/OWNERS b/core/java/android/service/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..09774f7
--- /dev/null
+++ b/core/java/android/service/ondeviceintelligence/OWNERS
@@ -0,0 +1 @@
+file:/core/java/android/app/ondeviceintelligence/OWNERS
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 2028c40..9db8aa1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -273,7 +273,7 @@
                 outerwidth /* ellipsizedWidth */, null /* ellipsize */, 1 /* maxLines */,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
                 null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false,
-                null);
+                false /* shiftDrawingOffsetForStartOverhang */, null);
 
         mEllipsizedWidth = outerwidth;
         mEllipsizedStart = 0;
@@ -346,7 +346,8 @@
                 ellipsizedWidth, ellipsize, 1 /* maxLines */,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
                 null /* rightIndents */, JUSTIFICATION_MODE_NONE,
-                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */, null);
+                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */,
+                false /* shiftDrawingOffsetForStartOverhang */, null);
     }
 
     /** @hide */
@@ -363,12 +364,14 @@
             TextUtils.TruncateAt ellipsize,
             Metrics metrics,
             boolean useBoundsForWidth,
+            boolean shiftDrawingOffsetForStartOverhang,
             @Nullable Paint.FontMetrics minimumFontMetrics) {
         this(text, paint, width, align, TextDirectionHeuristics.LTR,
                 spacingMult, spacingAdd, includePad, fallbackLineSpacing, ellipsizedWidth,
                 ellipsize, 1 /* maxLines */, Layout.BREAK_STRATEGY_SIMPLE,
                 Layout.HYPHENATION_FREQUENCY_NONE, null, null, Layout.JUSTIFICATION_MODE_NONE,
-                LineBreakConfig.NONE, metrics, useBoundsForWidth, minimumFontMetrics);
+                LineBreakConfig.NONE, metrics, useBoundsForWidth,
+                shiftDrawingOffsetForStartOverhang, minimumFontMetrics);
     }
 
     /* package */ BoringLayout(
@@ -392,12 +395,14 @@
             LineBreakConfig lineBreakConfig,
             Metrics metrics,
             boolean useBoundsForWidth,
+            boolean shiftDrawingOffsetForStartOverhang,
             @Nullable Paint.FontMetrics minimumFontMetrics) {
 
         super(text, paint, width, align, textDir, spacingMult, spacingAdd, includePad,
                 fallbackLineSpacing, ellipsizedWidth, ellipsize, maxLines, breakStrategy,
                 hyphenationFrequency, leftIndents, rightIndents, justificationMode,
-                lineBreakConfig, useBoundsForWidth, minimumFontMetrics);
+                lineBreakConfig, useBoundsForWidth, shiftDrawingOffsetForStartOverhang,
+                minimumFontMetrics);
 
 
         boolean trust;
@@ -712,7 +717,7 @@
                      int cursorOffset) {
         if (mDirect != null && highlight == null) {
             float leftShift = 0;
-            if (getUseBoundsForWidth()) {
+            if (getUseBoundsForWidth() && getShiftDrawingOffsetForStartOverhang()) {
                 RectF drawingRect = computeDrawingBoundingBox();
                 if (drawingRect.left < 0) {
                     leftShift = -drawingRect.left;
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 9286049..cce4f7b 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -25,6 +25,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -317,6 +318,35 @@
         }
 
         /**
+         * Set true for shifting the drawing x offset for showing overhang at the start position.
+         *
+         * This flag is ignored if the {@link #getUseBoundsForWidth()} is false.
+         *
+         * If this value is false, the Layout draws text from the zero even if there is a glyph
+         * stroke in a region where the x coordinate is negative.
+         *
+         * If this value is true, the Layout draws text with shifting the x coordinate of the
+         * drawing bounding box.
+         *
+         * This value is false by default.
+         *
+         * @param shiftDrawingOffsetForStartOverhang true for shifting the drawing offset for
+         *                                          showing the stroke that is in the region where
+         *                                          the x coordinate is negative.
+         * @see #setUseBoundsForWidth(boolean)
+         * @see #getUseBoundsForWidth()
+         */
+        @NonNull
+        // The corresponding getter is getShiftDrawingOffsetForStartOverhang()
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+        public Builder setShiftDrawingOffsetForStartOverhang(
+                boolean shiftDrawingOffsetForStartOverhang) {
+            mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
+            return this;
+        }
+
+        /**
          * Set the minimum font metrics used for line spacing.
          *
          * <p>
@@ -386,6 +416,7 @@
         private int mEllipsizedWidth;
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
+        private boolean mShiftDrawingOffsetForStartOverhang;
         private @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
         private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
@@ -462,7 +493,8 @@
                 false /* fallbackLineSpacing */, ellipsizedWidth, ellipsize,
                 Integer.MAX_VALUE /* maxLines */, breakStrategy, hyphenationFrequency,
                 null /* leftIndents */, null /* rightIndents */, justificationMode,
-                lineBreakConfig, false /* useBoundsForWidth */, null /* minimumFontMetrics */);
+                lineBreakConfig, false /* useBoundsForWidth */, false,
+                null /* minimumFontMetrics */);
 
         final Builder b = Builder.obtain(base, paint, width)
                 .setAlignment(align)
@@ -488,7 +520,8 @@
                 b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                 Integer.MAX_VALUE /* maxLines */, b.mBreakStrategy, b.mHyphenationFrequency,
                 null /* leftIndents */, null /* rightIndents */, b.mJustificationMode,
-                b.mLineBreakConfig, b.mUseBoundsForWidth, b.mMinimumFontMetrics);
+                b.mLineBreakConfig, b.mUseBoundsForWidth, b.mShiftDrawingOffsetForStartOverhang,
+                b.mMinimumFontMetrics);
 
         mDisplay = b.mDisplay;
         mIncludePad = b.mIncludePad;
@@ -516,6 +549,7 @@
         mBase = b.mBase;
         mFallbackLineSpacing = b.mFallbackLineSpacing;
         mUseBoundsForWidth = b.mUseBoundsForWidth;
+        mShiftDrawingOffsetForStartOverhang = b.mShiftDrawingOffsetForStartOverhang;
         mMinimumFontMetrics = b.mMinimumFontMetrics;
         if (b.mEllipsize != null) {
             mInts = new PackedIntVector(COLUMNS_ELLIPSIZE);
@@ -713,6 +747,7 @@
                 .setAddLastLineLineSpacing(!islast)
                 .setIncludePad(false)
                 .setUseBoundsForWidth(mUseBoundsForWidth)
+                .setShiftDrawingOffsetForStartOverhang(mShiftDrawingOffsetForStartOverhang)
                 .setMinimumFontMetrics(mMinimumFontMetrics)
                 .setCalculateBounds(true);
 
@@ -1392,6 +1427,7 @@
     private Rect mTempRect = new Rect();
 
     private boolean mUseBoundsForWidth;
+    private boolean mShiftDrawingOffsetForStartOverhang;
     @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
     @UnsupportedAppUsage
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index e5d199a..8e52af3 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -44,6 +44,7 @@
 import android.text.style.ParagraphStyle;
 import android.text.style.ReplacementSpan;
 import android.text.style.TabStopSpan;
+import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
@@ -299,7 +300,7 @@
         this(text, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingMult, spacingAdd, false, false, 0, null, Integer.MAX_VALUE,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null, null,
-                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null);
+                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, false, null);
     }
 
     /**
@@ -349,6 +350,7 @@
             int justificationMode,
             LineBreakConfig lineBreakConfig,
             boolean useBoundsForWidth,
+            boolean shiftDrawingOffsetForStartOverhang,
             Paint.FontMetrics minimumFontMetrics
     ) {
 
@@ -384,6 +386,7 @@
         mJustificationMode = justificationMode;
         mLineBreakConfig = lineBreakConfig;
         mUseBoundsForWidth = useBoundsForWidth;
+        mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
         mMinimumFontMetrics = minimumFontMetrics;
     }
 
@@ -465,7 +468,7 @@
             @Nullable Paint selectionPaint,
             int cursorOffsetVertical) {
         float leftShift = 0;
-        if (mUseBoundsForWidth) {
+        if (mUseBoundsForWidth && mShiftDrawingOffsetForStartOverhang) {
             RectF drawingRect = computeDrawingBoundingBox();
             if (drawingRect.left < 0) {
                 leftShift = -drawingRect.left;
@@ -3414,6 +3417,7 @@
     private int mJustificationMode;
     private LineBreakConfig mLineBreakConfig;
     private boolean mUseBoundsForWidth;
+    private boolean mShiftDrawingOffsetForStartOverhang;
     private @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
     private TextLine.LineInfo mLineInfo = null;
@@ -3873,6 +3877,35 @@
         }
 
         /**
+         * Set true for shifting the drawing x offset for showing overhang at the start position.
+         *
+         * This flag is ignored if the {@link #getUseBoundsForWidth()} is false.
+         *
+         * If this value is false, the Layout draws text from the zero even if there is a glyph
+         * stroke in a region where the x coordinate is negative.
+         *
+         * If this value is true, the Layout draws text with shifting the x coordinate of the
+         * drawing bounding box.
+         *
+         * This value is false by default.
+         *
+         * @param shiftDrawingOffsetForStartOverhang true for shifting the drawing offset for
+         *                                          showing the stroke that is in the region where
+         *                                          the x coordinate is negative.
+         * @see #setUseBoundsForWidth(boolean)
+         * @see #getUseBoundsForWidth()
+         */
+        @NonNull
+        // The corresponding getter is getShiftDrawingOffsetForStartOverhang()
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+        public Builder setShiftDrawingOffsetForStartOverhang(
+                boolean shiftDrawingOffsetForStartOverhang) {
+            mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
+            return this;
+        }
+
+        /**
          * Set the minimum font metrics used for line spacing.
          *
          * <p>
@@ -3948,6 +3981,7 @@
                         .setJustificationMode(mJustificationMode)
                         .setLineBreakConfig(mLineBreakConfig)
                         .setUseBoundsForWidth(mUseBoundsForWidth)
+                        .setShiftDrawingOffsetForStartOverhang(mShiftDrawingOffsetForStartOverhang)
                         .build();
             } else {
                 return new BoringLayout(
@@ -3955,7 +3989,7 @@
                         mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines,
                         mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents,
                         mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth,
-                        mMinimumFontMetrics);
+                        mShiftDrawingOffsetForStartOverhang, mMinimumFontMetrics);
             }
         }
 
@@ -3980,6 +4014,7 @@
         private int mJustificationMode = JUSTIFICATION_MODE_NONE;
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
+        private boolean mShiftDrawingOffsetForStartOverhang;
         private Paint.FontMetrics mMinimumFontMetrics;
     }
 
@@ -4294,6 +4329,20 @@
     }
 
     /**
+     * Returns true if shifting drawing offset for start overhang.
+     *
+     * @return True if shifting drawing offset for start overhang.
+     * @see android.widget.TextView#setShiftDrawingOffsetForStartOverhang(boolean)
+     * @see TextView#getShiftDrawingOffsetForStartOverhang()
+     * @see StaticLayout.Builder#setShiftDrawingOffsetForStartOverhang(boolean)
+     * @see DynamicLayout.Builder#setShiftDrawingOffsetForStartOverhang(boolean)
+     */
+    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+    public boolean getShiftDrawingOffsetForStartOverhang() {
+        return mShiftDrawingOffsetForStartOverhang;
+    }
+
+    /**
      * Get the minimum font metrics used for line spacing.
      *
      * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 5986238..3dd3a9e 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -24,6 +24,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 import android.graphics.RectF;
@@ -454,6 +455,35 @@
         }
 
         /**
+         * Set true for shifting the drawing x offset for showing overhang at the start position.
+         *
+         * This flag is ignored if the {@link #getUseBoundsForWidth()} is false.
+         *
+         * If this value is false, the Layout draws text from the zero even if there is a glyph
+         * stroke in a region where the x coordinate is negative.
+         *
+         * If this value is true, the Layout draws text with shifting the x coordinate of the
+         * drawing bounding box.
+         *
+         * This value is false by default.
+         *
+         * @param shiftDrawingOffsetForStartOverhang true for shifting the drawing offset for
+         *                                          showing the stroke that is in the region where
+         *                                          the x coordinate is negative.
+         * @see #setUseBoundsForWidth(boolean)
+         * @see #getUseBoundsForWidth()
+         */
+        @NonNull
+        // The corresponding getter is getShiftDrawingOffsetForStartOverhang()
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+        public Builder setShiftDrawingOffsetForStartOverhang(
+                boolean shiftDrawingOffsetForStartOverhang) {
+            mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
+            return this;
+        }
+
+        /**
          * Internal API that tells underlying line breaker that calculating bounding boxes even if
          * the line break is performed with advances. This is useful for DynamicLayout internal
          * implementation because it uses bounding box as well as advances.
@@ -566,6 +596,7 @@
         private boolean mAddLastLineLineSpacing;
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
+        private boolean mShiftDrawingOffsetForStartOverhang;
         private boolean mCalculateBounds;
         @Nullable private Paint.FontMetrics mMinimumFontMetrics;
 
@@ -599,6 +630,7 @@
                 JUSTIFICATION_MODE_NONE,
                 null,  // lineBreakConfig,
                 false,  // useBoundsForWidth
+                false,  // shiftDrawingOffsetForStartOverhang
                 null  // minimumFontMetrics
         );
 
@@ -677,7 +709,7 @@
                 b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                 b.mMaxLines, b.mBreakStrategy, b.mHyphenationFrequency, b.mLeftIndents,
                 b.mRightIndents, b.mJustificationMode, b.mLineBreakConfig, b.mUseBoundsForWidth,
-                b.mMinimumFontMetrics);
+                b.mShiftDrawingOffsetForStartOverhang, b.mMinimumFontMetrics);
 
         mColumns = columnSize;
         if (b.mEllipsize != null) {
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index 9413f5c..5ec41591 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -202,38 +202,4 @@
         throw new UnsupportedOperationException("The getInputTransferToken needs to be "
                 + "implemented before making this call.");
     }
-
-    /**
-     * Transfer the currently in progress touch gesture from the host to the requested
-     * {@link SurfaceControlViewHost.SurfacePackage}. This requires that the
-     * SurfaceControlViewHost was created with the current host's inputToken.
-     * <p>
-     * When the touch is transferred, the window currently receiving touch gets an ACTION_CANCEL
-     * and does not receive any further input events for this gesture.
-     * <p>
-     * The transferred-to window receives an ACTION_DOWN event and then the remainder of the
-     * input events for this gesture. It does not receive any of the previous events of this gesture
-     * that the originating window received.
-     * <p>
-     * The "transferTouch" API only works for the current gesture. When a new gesture arrives,
-     * input dispatcher will do a new round of hit testing. So, if the "host" window is still the
-     * first thing that's being touched, then it will receive the new gesture again. It will
-     * again be up to the host to transfer this new gesture to the embedded.
-     * <p>
-     * Once the transferred-to window receives the gesture, it can choose to give up this gesture
-     * and send it to another window that it's linked to (it can't be an arbitrary window for
-     * security reasons) using the same transferTouch API. Only the window currently receiving
-     * touch is allowed to transfer the gesture.
-     *
-     * @param surfacePackage The SurfacePackage to transfer the gesture to.
-     * @return Whether the touch stream was transferred.
-     * @see SurfaceControlViewHost#transferTouchGestureToHost() for the reverse to transfer touch
-     * gesture from the embedded to the host.
-     */
-    @FlaggedApi(Flags.FLAG_TRANSFER_GESTURE_TO_EMBEDDED)
-    default boolean transferHostTouchGestureToEmbedded(
-            @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
-        throw new UnsupportedOperationException(
-                "transferHostTouchGestureToEmbedded is unimplemented");
-    }
 }
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index eb28920..676b903 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -23,6 +23,9 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.text.TextUtils;
+import android.view.inputmethod.ConnectionlessHandwritingCallback;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.Flags;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
@@ -225,15 +228,7 @@
                             }
                             startHandwriting(candidateView);
                         } else if (candidateView.getHandwritingDelegatorCallback() != null) {
-                            String delegatePackageName =
-                                    candidateView.getAllowedHandwritingDelegatePackageName();
-                            if (delegatePackageName == null) {
-                                delegatePackageName = candidateView.getContext().getOpPackageName();
-                            }
-                            mImm.prepareStylusHandwritingDelegation(
-                                    candidateView, delegatePackageName);
-                            candidateView.getHandwritingDelegatorCallback().run();
-                            mState.mHasPreparedHandwritingDelegation = true;
+                            prepareDelegation(candidateView);
                         } else {
                             if (!mInitiateWithoutConnection) {
                                 mState.mPendingConnectedView = new WeakReference<>(candidateView);
@@ -375,7 +370,7 @@
             // A new view just gain focus. By default, we should show hover icon for it.
             mShowHoverIconForConnectedView = true;
         }
-        if (!fromTouchEvent) {
+        if (!fromTouchEvent && view.isHandwritingDelegate()) {
             tryAcceptStylusHandwritingDelegation(view);
         }
         return true;
@@ -393,15 +388,33 @@
         }
     }
 
+    private void prepareDelegation(View view) {
+        String delegatePackageName = view.getAllowedHandwritingDelegatePackageName();
+        if (delegatePackageName == null) {
+            delegatePackageName = view.getContext().getOpPackageName();
+        }
+        if (mImm.isConnectionlessStylusHandwritingAvailable()) {
+            // No other view should have focus during the connectionless handwriting session, as
+            // this could cause user confusion about the input target for the session.
+            view.getViewRootImpl().getView().clearFocus();
+            mImm.startConnectionlessStylusHandwritingForDelegation(
+                    view, getCursorAnchorInfoForConnectionless(view), delegatePackageName,
+                    view::post, new DelegationCallback(view, delegatePackageName));
+            mState.mHasInitiatedHandwriting = true;
+            mState.mShouldInitHandwriting = false;
+        } else {
+            mImm.prepareStylusHandwritingDelegation(view, delegatePackageName);
+            view.getHandwritingDelegatorCallback().run();
+            mState.mHasPreparedHandwritingDelegation = true;
+        }
+    }
+
     /**
      * Starts a stylus handwriting session for the delegate view, if {@link
      * InputMethodManager#prepareStylusHandwritingDelegation} was previously called.
      */
     @VisibleForTesting
     public boolean tryAcceptStylusHandwritingDelegation(@NonNull View view) {
-        if (!view.isHandwritingDelegate() || (mState != null && mState.mHasInitiatedHandwriting)) {
-            return false;
-        }
         String delegatorPackageName =
                 view.getAllowedHandwritingDelegatorPackageName();
         if (delegatorPackageName == null) {
@@ -807,6 +820,59 @@
                 && view.shouldInitiateHandwriting();
     }
 
+    private CursorAnchorInfo getCursorAnchorInfoForConnectionless(View view) {
+        CursorAnchorInfo.Builder builder = new CursorAnchorInfo.Builder();
+        // Fake editor views will usually display hint text. The hint text view can be used to
+        // populate the CursorAnchorInfo.
+        TextView textView = findFirstTextViewDescendent(view);
+        if (textView != null) {
+            textView.getCursorAnchorInfo(0, builder, mTempMatrix);
+            if (textView.getSelectionStart() < 0) {
+                // Insertion marker location is not populated if selection start is negative, so
+                // make a best guess.
+                float bottom = textView.getHeight() - textView.getExtendedPaddingBottom();
+                builder.setInsertionMarkerLocation(
+                        /* horizontalPosition= */ textView.getCompoundPaddingStart(),
+                        /* lineTop= */ textView.getExtendedPaddingTop(),
+                        /* lineBaseline= */ bottom,
+                        /* lineBottom= */ bottom,
+                        /* flags= */ 0);
+            }
+        } else {
+            // If there is no TextView descendent, just populate the insertion marker with the start
+            // edge of the view.
+            mTempMatrix.reset();
+            view.transformMatrixToGlobal(mTempMatrix);
+            builder.setMatrix(mTempMatrix);
+            builder.setInsertionMarkerLocation(
+                    /* horizontalPosition= */ view.isLayoutRtl() ? view.getWidth() : 0,
+                    /* lineTop= */ 0,
+                    /* lineBaseline= */ view.getHeight(),
+                    /* lineBottom= */ view.getHeight(),
+                    /* flags= */ 0);
+        }
+        return builder.build();
+    }
+
+    @Nullable
+    private static TextView findFirstTextViewDescendent(View view) {
+        if (view instanceof ViewGroup viewGroup) {
+            TextView textView;
+            for (int i = 0; i < viewGroup.getChildCount(); ++i) {
+                View child = viewGroup.getChildAt(i);
+                textView = (child instanceof TextView tv)
+                        ? tv : findFirstTextViewDescendent(viewGroup.getChildAt(i));
+                if (textView != null
+                        && textView.isAggregatedVisible()
+                        && (!TextUtils.isEmpty(textView.getText())
+                                || !TextUtils.isEmpty(textView.getHint()))) {
+                    return textView;
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * A class used to track the handwriting areas set by the Views.
      *
@@ -931,4 +997,35 @@
             return true;
         }
     }
+
+    private class DelegationCallback implements ConnectionlessHandwritingCallback {
+        private final View mView;
+        private final String mDelegatePackageName;
+
+        private DelegationCallback(View view, String delegatePackageName) {
+            mView = view;
+            mDelegatePackageName = delegatePackageName;
+        }
+
+        @Override
+        public void onResult(@NonNull CharSequence text) {
+            mView.getHandwritingDelegatorCallback().run();
+        }
+
+        @Override
+        public void onError(int errorCode) {
+            switch (errorCode) {
+                case CONNECTIONLESS_HANDWRITING_ERROR_NO_TEXT_RECOGNIZED:
+                    mView.getHandwritingDelegatorCallback().run();
+                    break;
+                case CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED:
+                    // Fall back to the old delegation flow
+                    mImm.prepareStylusHandwritingDelegation(mView, mDelegatePackageName);
+                    mView.getHandwritingDelegatorCallback().run();
+                    mState.mHasInitiatedHandwriting = false;
+                    mState.mHasPreparedHandwritingDelegation = true;
+                    break;
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 29cc859..c475f6b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -1098,4 +1098,7 @@
      * (ie. not handled by any window which can handle the drag).
      */
     void setUnhandledDragListener(IUnhandledDragListener listener);
+
+    boolean transferTouchGesture(in InputTransferToken transferFromToken,
+            in InputTransferToken transferToToken);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 55e49f8..d68a47c 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -370,11 +370,6 @@
      */
     boolean cancelDraw(IWindow window);
 
-    boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow);
-
-    boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
-        in InputTransferToken transferTouchToken);
-
     /**
      * Moves the focus to the adjacent window if there is one in the given direction. This can only
      * move the focus to the window in the same leaf task.
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 1dd9cbb..06a923a 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -293,12 +293,12 @@
         /**
          * Gets an {@link InputTransferToken} which can be used to request focus on the embedded
          * surface or to transfer touch gesture to the embedded surface.
-         * @return the InputTransferToken associated with {@link SurfacePackage}
-         * @see AttachedSurfaceControl#transferHostTouchGestureToEmbedded(SurfacePackage)
-         *
-         * @hide
+         * @return the InputTransferToken associated with {@link SurfacePackage} or {@code null} if
+         * the embedded hasn't set up its view or doesn't have input.
+         * @see WindowManager#transferTouchGesture(InputTransferToken, InputTransferToken)
          */
         @Nullable
+        @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
         public InputTransferToken getInputTransferToken() {
             return mInputTransferToken;
         }
@@ -577,9 +577,9 @@
     }
 
     /**
-     * Transfer the currently in progress touch gesture to the parent
-     * (if any) of this SurfaceControlViewHost. This requires that the
-     * SurfaceControlViewHost was created with an associated hostInputToken.
+     * Transfer the currently in progress touch gesture to the parent (if any) of this
+     * SurfaceControlViewHost. This requires that the SurfaceControlViewHost was created with an
+     * associated host {@link InputTransferToken}.
      *
      * @return Whether the touch stream was transferred.
      */
@@ -587,13 +587,14 @@
         if (mViewRoot == null) {
             return false;
         }
-
-        final IWindowSession realWm = WindowManagerGlobal.getWindowSession();
-        try {
-            return realWm.transferEmbeddedTouchFocusToHost(mViewRoot.mWindow);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
+        final WindowManager wm =
+                (WindowManager) mViewRoot.mContext.getSystemService(Context.WINDOW_SERVICE);
+        InputTransferToken embeddedToken = getInputTransferToken();
+        InputTransferToken hostToken = mWm.mHostInputTransferToken;
+        if (embeddedToken == null || hostToken == null) {
+            Log.w(TAG, "Failed to transferTouchGestureToHost. Host or embedded token is null");
+            return false;
         }
-        return false;
+        return wm.transferTouchGesture(getInputTransferToken(), mWm.mHostInputTransferToken);
     }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 25ade62..73b6ed6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5638,7 +5638,7 @@
     private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
 
     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
-    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = 0;
+    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
     public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
@@ -33457,7 +33457,6 @@
         if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
             return FRAME_RATE_CATEGORY_NORMAL;
         }
-
         return mLastFrameRateCategory;
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 657c8e6..9474a69 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -27,6 +27,8 @@
 import static android.view.InsetsSource.ID_IME;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
+import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
+import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
@@ -1031,6 +1033,15 @@
     private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100;
 
     /*
+     * The variables below are used to update frame rate category
+     */
+    private static final int FRAME_RATE_CATEGORY_COUNT = 5;
+    private int mFrameRateCategoryHighCount = 0;
+    private int mFrameRateCategoryHighHintCount = 0;
+    private int mFrameRateCategoryNormalCount = 0;
+    private int mFrameRateCategoryLowCount = 0;
+
+    /*
      * the variables below are used to determine whther a dVRR feature should be enabled
      */
 
@@ -4084,7 +4095,14 @@
         // when the values are applicable.
         setPreferredFrameRate(mPreferredFrameRate);
         setPreferredFrameRateCategory(mPreferredFrameRateCategory);
+        mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
+                ? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
+        mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
+                ? mFrameRateCategoryNormalCount - 1 : mFrameRateCategoryNormalCount;
+        mFrameRateCategoryLowCount = mFrameRateCategoryLowCount > 0
+                ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount;
         mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
+        mPreferredFrameRate = -1;
     }
 
     private void createSyncIfNeeded() {
@@ -12296,7 +12314,8 @@
         }
 
         try {
-            if (mLastPreferredFrameRate != preferredFrameRate) {
+            if (mLastPreferredFrameRate != preferredFrameRate
+                    && preferredFrameRate >= 0) {
                 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                     Trace.traceBegin(
                             Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRate "
@@ -12346,7 +12365,25 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
     public void votePreferredFrameRateCategory(int frameRateCategory) {
-        mPreferredFrameRateCategory = Math.max(mPreferredFrameRateCategory, frameRateCategory);
+        if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH) {
+            mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
+        } else if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH_HINT) {
+            mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
+        } else if (frameRateCategory == FRAME_RATE_CATEGORY_NORMAL) {
+            mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
+        } else if (frameRateCategory == FRAME_RATE_CATEGORY_LOW) {
+            mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
+        }
+
+        if (mFrameRateCategoryHighCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
+        } else if (mFrameRateCategoryHighHintCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH_HINT;
+        } else if (mFrameRateCategoryNormalCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NORMAL;
+        } else if (mFrameRateCategoryLowCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_LOW;
+        }
         mHasInvalidation = true;
     }
 
@@ -12368,13 +12405,7 @@
             return;
         }
 
-        if (mPreferredFrameRate == 0) {
-            mPreferredFrameRate = frameRate;
-        } else if (frameRate > 60 || mPreferredFrameRate > 60) {
-            mPreferredFrameRate = Math.max(mPreferredFrameRate, frameRate);
-        } else if (mPreferredFrameRate != frameRate) {
-            mPreferredFrameRate = 60;
-        }
+        mPreferredFrameRate = Math.max(mPreferredFrameRate, frameRate);
 
         mHasInvalidation = true;
         mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
@@ -12403,7 +12434,7 @@
      */
     @VisibleForTesting
     public float getPreferredFrameRate() {
-        return mPreferredFrameRate;
+        return mPreferredFrameRate >= 0 ? mPreferredFrameRate : mLastPreferredFrameRate;
     }
 
     /**
@@ -12431,19 +12462,6 @@
                 boostTimeOut);
     }
 
-    @Override
-    public boolean transferHostTouchGestureToEmbedded(
-            @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
-        final IWindowSession realWm = WindowManagerGlobal.getWindowSession();
-        try {
-            return realWm.transferHostTouchGestureToEmbedded(mWindow,
-                    surfacePackage.getInputTransferToken());
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-        return false;
-    }
-
     /**
      * Set the default back key callback for windowless window, to forward the back key event
      * to host app.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0302a0d..4e13878 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1548,6 +1548,48 @@
             "android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI";
 
     /**
+     * Application or Activity level
+     * {@link android.content.pm.PackageManager.Property PackageManager.Property} to provide any
+     * preferences for showing all or specific Activities on small cover displays of foldable
+     * style devices.
+     *
+     * <p>The only supported value for the property is {@link #COMPAT_SMALL_COVER_SCREEN_OPT_IN}.
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name="android.window.PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN"
+     *     android:value=1 <!-- COMPAT_COVER_SCREEN_OPT_IN -->/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     */
+    @FlaggedApi(Flags.FLAG_COVER_DISPLAY_OPT_IN)
+    String PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN =
+            "android.window.PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN";
+
+    /**
+     * Value applicable for the {@link #PROPERTY_COMPAT_ALLOW_SMALL_COVER_SCREEN} property to
+     * provide a signal to the system that an application or its specific activities explicitly
+     * opt into being displayed on small foldable device cover screens that measure at least 1.5
+     * inches for the shorter dimension and at least 2.4 inches for the longer dimension.
+     */
+    @CompatSmallScreenPolicy
+    @FlaggedApi(Flags.FLAG_COVER_DISPLAY_OPT_IN)
+    int COMPAT_SMALL_COVER_SCREEN_OPT_IN = 1;
+
+    /**
+     * @hide
+     */
+    @IntDef({
+            COMPAT_SMALL_COVER_SCREEN_OPT_IN,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface CompatSmallScreenPolicy {}
+
+
+
+    /**
      * Request for app's keyboard shortcuts to be retrieved asynchronously.
      *
      * @param receiver The callback to be triggered when the result is ready.
@@ -6196,6 +6238,54 @@
     }
 
     /**
+     * Transfer the currently in progress touch gesture from the transferFromToken to the
+     * transferToToken.
+     * <p><br>
+     * This requires that the fromToken and toToken are associated with each other. The association
+     * can be done by creating a {@link SurfaceControlViewHost} and passing the host's
+     * {@link InputTransferToken} for
+     * {@link SurfaceControlViewHost#SurfaceControlViewHost(Context, Display, InputTransferToken)}.
+     * <p>
+     * The host is likely to be an {@link AttachedSurfaceControl} so the host token can be
+     * retrieved via {@link AttachedSurfaceControl#getInputTransferToken()}.
+     * <p><br>
+     * Only the window currently receiving touch is allowed to transfer the gesture so if the caller
+     * attempts to transfer touch gesture from a token that doesn't have touch, it will fail the
+     * transfer.
+     * <p><br>
+     * When the host wants to transfer touch gesture to the embedded, it can retrieve the embedded
+     * token via {@link SurfaceControlViewHost.SurfacePackage#getInputTransferToken()} and pass its
+     * own token as the transferFromToken.
+     * <p>
+     * When the embedded wants to transfer touch gesture to the host, it can pass in its own token
+     * as the transferFromToken and use the associated host's {@link InputTransferToken} as the
+     * transferToToken
+     * <p><br>
+     * When the touch is transferred, the window currently receiving touch gets an ACTION_CANCEL
+     * and does not receive any further input events for this gesture.
+     * <p>
+     * The transferred-to window receives an ACTION_DOWN event and then the remainder of the input
+     * events for this gesture. It does not receive any of the previous events of this gesture that
+     * the originating window received.
+     * <p>
+     * The transferTouchGesture API only works for the current gesture. When a new gesture arrives,
+     * input dispatcher will do a new round of hit testing. So, if the host window is still the
+     * first thing that's being touched, then it will receive the new gesture again. It will again
+     * be up to the host to transfer this new gesture to the embedded.
+     *
+     * @param transferFromToken the InputTransferToken for the currently active gesture
+     * @param transferToToken   the InputTransferToken to transfer the gesture to.
+     * @return Whether the touch stream was transferred.
+     * @see android.view.SurfaceControlViewHost.SurfacePackage#getInputTransferToken()
+     * @see AttachedSurfaceControl#getInputTransferToken()
+     */
+    @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
+    default boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken,
+            @NonNull InputTransferToken transferToToken) {
+        throw new UnsupportedOperationException("transferTouchGesture is not implemented");
+    }
+
+    /**
      * @hide
      */
     default @NonNull IBinder getDefaultToken() {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 1428963..2c98d9a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -930,6 +930,17 @@
         return surfaceControlInputReceiverInfo.mClientToken;
     }
 
+    boolean transferTouchGesture(InputTransferToken transferFromToken,
+            InputTransferToken transferToToken) {
+        try {
+            return getWindowManagerService().transferTouchGesture(transferFromToken,
+                    transferToToken);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+        return false;
+    }
+
     private final class TrustedPresentationListener extends
             ITrustedPresentationListener.Stub {
         private static int sId = 0;
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 1e3d062..44e2493 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -563,6 +563,14 @@
     }
 
     @Override
+    public boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken,
+            @NonNull InputTransferToken transferToToken) {
+        Objects.requireNonNull(transferFromToken);
+        Objects.requireNonNull(transferToToken);
+        return mGlobal.transferTouchGesture(transferFromToken, transferToToken);
+    }
+
+    @Override
     public @ScreenRecordingState int addScreenRecordingCallback(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull Consumer<@ScreenRecordingState Integer> callback) {
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 3f1ae51..2b2c507 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -651,21 +651,6 @@
     }
 
     @Override
-    public boolean transferEmbeddedTouchFocusToHost(IWindow window) {
-        Log.e(TAG, "Received request to transferEmbeddedTouch focus on WindowlessWindowManager" +
-            " we shouldn't get here!");
-        return false;
-    }
-
-    @Override
-    public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
-            InputTransferToken embeddedInputToken) {
-        Log.e(TAG, "Received request to transferHostTouchGestureToEmbedded on"
-                + " WindowlessWindowManager. We shouldn't get here!");
-        return false;
-    }
-
-    @Override
     public boolean moveFocusToAdjacentWindow(IWindow fromWindow, @FocusDirection int direction) {
         Log.e(TAG, "Received request to moveFocusToAdjacentWindow on"
                 + " WindowlessWindowManager. We shouldn't get here!");
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 57e4e6a..9847cb1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -181,6 +181,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewHierarchyEncoder;
 import android.view.ViewParent;
@@ -866,6 +867,7 @@
     private final boolean mUseTextPaddingForUiTranslation;
 
     private boolean mUseBoundsForWidth;
+    private boolean mShiftDrawingOffsetForStartOverhang;
     @Nullable private Paint.FontMetrics mMinimumFontMetrics;
     @Nullable private Paint.FontMetrics mLocalePreferredFontMetrics;
     private boolean mUseLocalePreferredLineHeightForMinimum;
@@ -1621,6 +1623,10 @@
                     hasUseBoundForWidthValue = true;
                     break;
                 case com.android.internal.R.styleable
+                        .TextView_shiftDrawingOffsetForStartOverhang:
+                    mShiftDrawingOffsetForStartOverhang = a.getBoolean(attr, false);
+                    break;
+                case com.android.internal.R.styleable
                         .TextView_useLocalePreferredLineHeightForMinimum:
                     mUseLocalePreferredLineHeightForMinimum = a.getBoolean(attr, false);
                     break;
@@ -4922,6 +4928,8 @@
      * @param useBoundsForWidth true for using bounding box for width. false for using advances for
      *                          width.
      * @see #getUseBoundsForWidth()
+     * @see #setShiftDrawingOffsetForStartOverhang(boolean)
+     * @see #getShiftDrawingOffsetForStartOverhang()
      */
     @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
     public void setUseBoundsForWidth(boolean useBoundsForWidth) {
@@ -4939,6 +4947,8 @@
      * Returns true if using bounding box as a width, false for using advance as a width.
      *
      * @see #setUseBoundsForWidth(boolean)
+     * @see #setShiftDrawingOffsetForStartOverhang(boolean)
+     * @see #getShiftDrawingOffsetForStartOverhang()
      * @return True if using bounding box for width, false if using advance for width.
      */
     @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
@@ -4947,6 +4957,53 @@
     }
 
     /**
+     * Set true for shifting the drawing x offset for showing overhang at the start position.
+     *
+     * This flag is ignored if the {@link #getUseBoundsForWidth()} is false.
+     *
+     * If this value is false, the TextView draws text from the zero even if there is a glyph stroke
+     * in a region where the x coordinate is negative. TextView clips the stroke in the region where
+     * the X coordinate is negative unless the parents has {@link ViewGroup#getClipChildren()} to
+     * true. This is useful for aligning multiple TextViews vertically.
+     *
+     * If this value is true, the TextView draws text with shifting the x coordinate of the drawing
+     * bounding box. This prevents the clipping even if the parents doesn't have
+     * {@link ViewGroup#getClipChildren()} to true.
+     *
+     * This value is false by default.
+     *
+     * @param shiftDrawingOffsetForStartOverhang true for shifting the drawing offset for showing
+     *                                           the stroke that is in the region whre the x
+     *                                           coorinate is negative.
+     * @see #setUseBoundsForWidth(boolean)
+     * @see #getUseBoundsForWidth()
+     */
+    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+    public void setShiftDrawingOffsetForStartOverhang(boolean shiftDrawingOffsetForStartOverhang) {
+        if (mShiftDrawingOffsetForStartOverhang != shiftDrawingOffsetForStartOverhang) {
+            mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
+            if (mLayout != null) {
+                nullLayouts();
+                requestLayout();
+                invalidate();
+            }
+        }
+    }
+
+    /**
+     * Returns true if shifting the drawing x offset for start overhang.
+     *
+     * @see #setShiftDrawingOffsetForStartOverhang(boolean)
+     * @see #setUseBoundsForWidth(boolean)
+     * @see #getUseBoundsForWidth()
+     * @return True if shifting the drawing x offset for start overhang.
+     */
+    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
+    public boolean getShiftDrawingOffsetForStartOverhang() {
+        return mShiftDrawingOffsetForStartOverhang;
+    }
+
+    /**
      * Set the minimum font metrics used for line spacing.
      *
      * <p>
@@ -11001,6 +11058,7 @@
                                 null,
                                 boring,
                                 mUseBoundsForWidth,
+                                mShiftDrawingOffsetForStartOverhang,
                                 getResolvedMinimumFontMetrics());
                     }
 
@@ -11028,6 +11086,7 @@
                                 effectiveEllipsize,
                                 boring,
                                 mUseBoundsForWidth,
+                                mShiftDrawingOffsetForStartOverhang,
                                 getResolvedMinimumFontMetrics());
                     }
                 }
diff --git a/core/java/android/window/InputTransferToken.java b/core/java/android/window/InputTransferToken.java
index bed0e0e..f1b37bf 100644
--- a/core/java/android/window/InputTransferToken.java
+++ b/core/java/android/window/InputTransferToken.java
@@ -31,6 +31,11 @@
 /**
  * A token that can be used to request focus on or to transfer touch gesture to a
  * {@link SurfaceControlViewHost} or {@link android.view.SurfaceControl} that has an input channel.
+ * <p>
+ * For {@link SurfaceControlViewHost}, the token can be retrieved via
+ * {@link SurfaceControlViewHost.SurfacePackage#getInputTransferToken()}
+ *
+ * @see android.view.WindowManager#transferTouchGesture(InputTransferToken, InputTransferToken)
  */
 @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
 public final class InputTransferToken implements Parcelable {
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index 3ffa274..8b3bd97 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -20,13 +20,6 @@
 
 flag {
     namespace: "window_surfaces"
-    name: "transfer_gesture_to_embedded"
-    description: "Enable public API for Window Surfaces"
-    bug: "287076178"
-}
-
-flag {
-    namespace: "window_surfaces"
     name: "delete_capture_display"
     description: "Delete uses of ScreenCapture#captureDisplay"
     is_fixed_read_only: true
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index bc63881..ce74848 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -69,4 +69,12 @@
     name: "embedded_activity_back_nav_flag"
     description: "Refines embedded activity back navigation behavior"
     bug: "293642394"
+}
+
+flag {
+    namespace: "windowing_sdk"
+    name: "cover_display_opt_in"
+    description: "Properties to allow apps and activities to opt-in to cover display rendering"
+    bug: "312530526"
+    is_fixed_read_only: true
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index d433ca3..73df5e8 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -408,6 +408,7 @@
     // Derived fields
     private long mLongVersionCode;
     private int mLocaleConfigRes;
+    private boolean mAllowCrossUidActivitySwitchFromBelow;
 
     private List<AndroidPackageSplit> mSplits;
 
@@ -1542,6 +1543,11 @@
     }
 
     @Override
+    public boolean isAllowCrossUidActivitySwitchFromBelow() {
+        return mAllowCrossUidActivitySwitchFromBelow;
+    }
+
+    @Override
     public boolean hasPreserveLegacyExternalStorage() {
         return getBoolean(Booleans.PRESERVE_LEGACY_EXTERNAL_STORAGE);
     }
@@ -2199,6 +2205,12 @@
     }
 
     @Override
+    public ParsingPackage setAllowCrossUidActivitySwitchFromBelow(boolean value) {
+        mAllowCrossUidActivitySwitchFromBelow = value;
+        return this;
+    }
+
+    @Override
     public PackageImpl setResourceOverlay(boolean value) {
         return setBoolean(Booleans.OVERLAY, value);
     }
@@ -2656,6 +2668,7 @@
         if (!mKnownActivityEmbeddingCerts.isEmpty()) {
             appInfo.setKnownActivityEmbeddingCerts(mKnownActivityEmbeddingCerts);
         }
+        appInfo.allowCrossUidActivitySwitchFromBelow = mAllowCrossUidActivitySwitchFromBelow;
 
         return appInfo;
     }
@@ -3250,6 +3263,7 @@
         dest.writeInt(this.uid);
         dest.writeLong(this.mBooleans);
         dest.writeLong(this.mBooleans2);
+        dest.writeBoolean(this.mAllowCrossUidActivitySwitchFromBelow);
     }
 
     public PackageImpl(Parcel in) {
@@ -3411,6 +3425,7 @@
         this.uid = in.readInt();
         this.mBooleans = in.readLong();
         this.mBooleans2 = in.readLong();
+        this.mAllowCrossUidActivitySwitchFromBelow = in.readBoolean();
 
         assignDerivedFields();
         assignDerivedFields2();
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
index ef106e0..5d185af 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
@@ -374,6 +374,9 @@
 
     ParsingPackage setZygotePreloadName(String zygotePreloadName);
 
+    ParsingPackage setAllowCrossUidActivitySwitchFromBelow(
+            boolean allowCrossUidActivitySwitchFromBelow);
+
     ParsingPackage sortActivities();
 
     ParsingPackage sortReceivers();
@@ -518,6 +521,8 @@
     @Nullable
     String getZygotePreloadName();
 
+    boolean isAllowCrossUidActivitySwitchFromBelow();
+
     boolean isBackupAllowed();
 
     boolean isTaskReparentingAllowed();
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index e0fdbc6..2e6053d 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -2374,8 +2374,10 @@
                 .setRestrictedAccountType(string(R.styleable.AndroidManifestApplication_restrictedAccountType, sa))
                 .setZygotePreloadName(string(R.styleable.AndroidManifestApplication_zygotePreloadName, sa))
                 // Non-Config String
-                .setPermission(nonConfigString(0, R.styleable.AndroidManifestApplication_permission, sa));
-        // CHECKSTYLE:on
+                .setPermission(nonConfigString(0, R.styleable.AndroidManifestApplication_permission, sa))
+                .setAllowCrossUidActivitySwitchFromBelow(bool(true, R.styleable.AndroidManifestApplication_allowCrossUidActivitySwitchFromBelow, sa));
+
+       // CHECKSTYLE:on
         //@formatter:on
     }
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b5b3a48..e46b8d7 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1615,7 +1615,8 @@
                         STRONG_AUTH_REQUIRED_AFTER_TIMEOUT,
                         STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
                         STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT,
-                        SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED})
+                        SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED,
+                        SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST})
         @Retention(RetentionPolicy.SOURCE)
         public @interface StrongAuthFlags {}
 
@@ -1641,7 +1642,8 @@
 
         /**
          * Strong authentication is required because the user has been locked out after too many
-         * attempts.
+         * attempts using primary auth methods (i.e. PIN/pattern/password) from the lock screen,
+         * Android Settings, and BiometricPrompt where user authentication is required.
          */
         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
 
@@ -1674,12 +1676,23 @@
         public static final int SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED = 0x100;
 
         /**
+         * Some authentication is required because adaptive auth has requested to lock device due to
+         * repeated failed primary auth (i.e. PIN/pattern/password) or biometric auth attempts which
+         * can come from Android Settings or BiometricPrompt where user authentication is required,
+         * in addition to from the lock screen. When a risk is determined, adaptive auth will
+         * proactively prompt the lock screen and will require users to re-enter the device with
+         * either primary auth or biometric auth (if not prohibited by other flags).
+         */
+        public static final int SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST = 0x200;
+
+        /**
          * Strong auth flags that do not prevent biometric methods from being accepted as auth.
          * If any other flags are set, biometric authentication is disabled.
          */
         private static final int ALLOWING_BIOMETRIC = STRONG_AUTH_NOT_REQUIRED
                 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST
-                | SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED;
+                | SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED
+                | SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
 
         private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
         private final H mHandler;
diff --git a/core/java/com/android/server/pm/pkg/AndroidPackage.java b/core/java/com/android/server/pm/pkg/AndroidPackage.java
index 096f246..d430fe3 100644
--- a/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -1507,4 +1507,11 @@
      * @hide
      */
     boolean isVisibleToInstantApps();
+
+    /**
+     * @see ApplicationInfo#allowCrossUidActivitySwitchFromBelow
+     * @see R.styleable#AndroidManifestApplication_allowCrossUidActivitySwitchFromBelow
+     * @hide
+     */
+    boolean isAllowCrossUidActivitySwitchFromBelow();
 }
diff --git a/core/proto/android/content/package_item_info.proto b/core/proto/android/content/package_item_info.proto
index b9905e8..b7408a4 100644
--- a/core/proto/android/content/package_item_info.proto
+++ b/core/proto/android/content/package_item_info.proto
@@ -113,6 +113,7 @@
         optional int32 enable_gwp_asan = 19;
         optional int32 enable_memtag = 20;
         optional bool native_heap_zero_init = 21;
+        optional bool allow_cross_uid_activity_switch_from_below = 22;
     }
     optional Detail detail = 17;
     repeated string overlay_paths = 18;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e7df19c..4131644 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3793,6 +3793,14 @@
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK"
                 android:protectionLevel="internal|role" />
 
+    <!-- Allows an application to manage policy related to theft detection.
+        @FlaggedApi("android.app.admin.flags.device_theft_api_enabled")
+        @hide
+        @SystemApi
+    -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION"
+                android:protectionLevel="internal|role" />
+
     <!-- Allows an application to manage policy related to system apps.
         <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
         APIs protected by this permission on users different to the calling user.
@@ -3830,6 +3838,24 @@
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS"
         android:protectionLevel="internal|role" />
 
+    <!-- Allows an application to manage policy related to block package uninstallation.
+        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+    -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL"
+        android:protectionLevel="internal|role" />
+
+    <!-- Allows an application to manage policy related to camera toggle.
+        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+    -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE"
+        android:protectionLevel="internal|role" />
+
+    <!-- Allows an application to manage policy related to microphone toggle.
+        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+    -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE"
+        android:protectionLevel="internal|role" />
+
     <!-- Allows an application to set device policies outside the current user
         that are critical for securing data within the current user.
         <p>Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_*
@@ -6884,13 +6910,10 @@
     <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows an application to manage media projection sessions, by showing the permission dialog
-         to the user and creating a new token for each capture session.
-         @FlaggedApi("com.android.media.flags.limit_manage_media_projection")
-         @SystemApi Only granted to apps holding role SYSTEM_UI.
+    <!-- Api Allows an application to manage media projection sessions.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
-        android:protectionLevel="internal|role" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to read install sessions
          @hide This is not a third-party API (intended for system apps). -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4ee03de..cc6460e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5891,6 +5891,17 @@
           use glyph bound's as a source of text width.  -->
         <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
         <attr name="useBoundsForWidth" format="boolean" />
+
+
+        <!-- Whether to shift the drawing offset for prevent clipping start drawing offset.
+          This value is ignored when the useBoundsForWidth attribute is false.
+
+          If this value is false, the TextView draws text from the zero X coordinate. This is
+          useful for aligning multiple TextViews vertically.
+          If this value is true, the TextView shift the drawing offset not to clip the
+          stroke in the region where the X coordinate is negative. -->
+        <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+        <attr name="shiftDrawingOffsetForStartOverhang" format="boolean" />
         <!-- Whether to use the locale preferred line height for the minimum line height.
 
           This flag is useful for preventing jitter of entering letters into empty EditText.
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 734ff8d..b2e0be7c 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1919,6 +1919,12 @@
              try to load its code when launching components.  The default is true
              for normal behavior. -->
         <attr name="hasCode" format="boolean" />
+        <!-- Specifies if activities can be launched on top of this application by activities from
+             other applications in the same task. If set to false, activity launches which would
+             replace this application with another when in the user's view will be blocked.
+             The default is true. -->
+        <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+        <attr name="allowCrossUidActivitySwitchFromBelow" format="boolean" />
         <attr name="persistent" />
         <attr name="persistentWhenFeatureAvailable" />
         <attr name="requiredForAllUsers" />
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index dcb6bb0..8af8cb8 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -159,6 +159,12 @@
     <public name="contentSensitivity" />
     <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
     <public name="supportsConnectionlessStylusHandwriting" />
+    <!-- @FlaggedApi("android.nfc.Flags.FLAG_OBSERVE_MODE") -->
+    <public name="defaultToObserveMode"/>
+    <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+    <public name="allowCrossUidActivitySwitchFromBelow"/>
+    <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+    <public name="shiftDrawingOffsetForStartOverhang" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01bc0000">
diff --git a/core/tests/BroadcastRadioTests/TEST_MAPPING b/core/tests/BroadcastRadioTests/TEST_MAPPING
index b085a27..5637063 100644
--- a/core/tests/BroadcastRadioTests/TEST_MAPPING
+++ b/core/tests/BroadcastRadioTests/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "BroadcastRadioTests"
     }
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 2327b20..48ef7e6 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -40,6 +40,7 @@
 import android.app.Application;
 import android.app.IApplicationThread;
 import android.app.PictureInPictureParams;
+import android.app.PictureInPictureUiState;
 import android.app.ResourcesManager;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ActivityLifecycleItem;
@@ -706,6 +707,9 @@
         final TestActivity activity = mActivityTestRule.launchActivity(startIntent);
         final ActivityThread activityThread = activity.getActivityThread();
         final ActivityClientRecord r = getActivityClientRecord(activity);
+        if (android.app.Flags.enablePipUiStateCallbackOnEntering()) {
+            activity.mPipUiStateLatch = new CountDownLatch(1);
+        }
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             activityThread.handlePictureInPictureRequested(r);
@@ -940,6 +944,11 @@
          * latch reaches 0.
          */
         volatile CountDownLatch mConfigLatch;
+        /**
+         * A latch used to notify tests that we're about to wait for the
+         * onPictureInPictureUiStateChanged callback.
+         */
+        volatile CountDownLatch mPipUiStateLatch;
 
         @Override
         protected void onCreate(Bundle savedInstanceState) {
@@ -974,6 +983,14 @@
             if (getIntent().getBooleanExtra(PIP_REQUESTED_OVERRIDE_ENTER, false)) {
                 enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
                 mPipEntered = true;
+                // Await for onPictureInPictureUiStateChanged callback if applicable
+                if (mPipUiStateLatch != null) {
+                    try {
+                        mPipUiStateLatch.await(TIMEOUT_SEC, TimeUnit.SECONDS);
+                    } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
+                    }
+                }
                 return true;
             } else if (getIntent().getBooleanExtra(PIP_REQUESTED_OVERRIDE_SKIP, false)) {
                 mPipEnterSkipped = true;
@@ -982,6 +999,13 @@
             return super.onPictureInPictureRequested();
         }
 
+        @Override
+        public void onPictureInPictureUiStateChanged(PictureInPictureUiState pipState) {
+            if (mPipUiStateLatch != null && pipState.isEnteringPip()) {
+                mPipUiStateLatch.countDown();
+            }
+        }
+
         boolean pipRequested() {
             return mPipRequested;
         }
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 0657e4b..433d353 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -660,10 +660,22 @@
     public void votePreferredFrameRate_voteFrameRateCategory_aggregate() {
         View view = new View(sContext);
         attachViewToWindow(view);
+        ViewRootImpl viewRootImpl = view.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
-            ViewRootImpl viewRootImpl = view.getViewRootImpl();
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                     FRAME_RATE_CATEGORY_NO_PREFERENCE);
+        });
+
+        // reset the frame rate category counts
+        for (int i = 0; i < 5; i++) {
+            sInstrumentation.runOnMainSync(() -> {
+                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                view.invalidate();
+            });
+            sInstrumentation.waitForIdleSync();
+        }
+
+        sInstrumentation.runOnMainSync(() -> {
             viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW);
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
             viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL);
@@ -699,6 +711,8 @@
             viewRootImpl.votePreferredFrameRate(24);
             assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1);
             viewRootImpl.votePreferredFrameRate(30);
+            assertEquals(viewRootImpl.getPreferredFrameRate(), 30, 0.1);
+            viewRootImpl.votePreferredFrameRate(60);
             assertEquals(viewRootImpl.getPreferredFrameRate(), 60, 0.1);
             viewRootImpl.votePreferredFrameRate(120);
             assertEquals(viewRootImpl.getPreferredFrameRate(), 120, 0.1);
@@ -721,6 +735,18 @@
         sInstrumentation.runOnMainSync(() -> {
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                     FRAME_RATE_CATEGORY_NO_PREFERENCE);
+        });
+
+        // reset the frame rate category counts
+        for (int i = 0; i < 5; i++) {
+            sInstrumentation.runOnMainSync(() -> {
+                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                view.invalidate();
+            });
+            sInstrumentation.waitForIdleSync();
+        }
+
+        sInstrumentation.runOnMainSync(() -> {
             view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
             view.invalidate();
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
@@ -847,7 +873,18 @@
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                     FRAME_RATE_CATEGORY_NO_PREFERENCE);
             assertEquals(viewRootImpl.getPreferredFrameRate(), frameRate, 0.1);
+        });
 
+        // reset the frame rate category counts
+        for (int i = 0; i < 5; i++) {
+            sInstrumentation.runOnMainSync(() -> {
+                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                view.invalidate();
+            });
+            sInstrumentation.waitForIdleSync();
+        }
+
+        sInstrumentation.runOnMainSync(() -> {
             view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
             view.invalidate();
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
@@ -882,18 +919,6 @@
 
         ViewRootImpl viewRootImpl = view.getViewRootImpl();
 
-        // Frequent update
-        sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-        });
-
         // In transistion from frequent update to infrequent update
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
@@ -901,9 +926,28 @@
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
         });
 
+        // reset the frame rate category counts
+        for (int i = 0; i < 5; i++) {
+            sInstrumentation.runOnMainSync(() -> {
+                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                view.invalidate();
+            });
+            sInstrumentation.waitForIdleSync();
+        }
+
+        // In transistion from frequent update to infrequent update
+        Thread.sleep(delay);
+        sInstrumentation.runOnMainSync(() -> {
+            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            view.invalidate();
+            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
+                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+        });
+
         // Infrequent update
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
+            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
             view.invalidate();
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
         });
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
index 396d403..fb5e512 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
@@ -16,8 +16,8 @@
 
 package android.hardware.devicestate;
 
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
@@ -39,18 +39,18 @@
 public final class DeviceStateTest {
     @Test
     public void testConstruct() {
-        final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE /* identifier */,
+        final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
                 "TEST_CLOSED" /* name */, DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS /* flags */);
-        assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE);
+        assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE_IDENTIFIER);
         assertEquals(state.getName(), "TEST_CLOSED");
         assertEquals(state.getFlags(), DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS);
     }
 
     @Test
     public void testConstruct_nullName() {
-        final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE /* identifier */,
+        final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
                 null /* name */, 0/* flags */);
-        assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE);
+        assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE_IDENTIFIER);
         assertNull(state.getName());
         assertEquals(state.getFlags(), 0);
     }
@@ -58,7 +58,8 @@
     @Test
     public void testConstruct_tooLargeIdentifier() {
         assertThrows(IllegalArgumentException.class, () -> {
-            final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE + 1 /* identifier */,
+            final DeviceState state = new DeviceState(
+                    MAXIMUM_DEVICE_STATE_IDENTIFIER + 1 /* identifier */,
                     null /* name */, 0 /* flags */);
         });
     }
@@ -66,7 +67,8 @@
     @Test
     public void testConstruct_tooSmallIdentifier() {
         assertThrows(IllegalArgumentException.class, () -> {
-            final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE - 1 /* identifier */,
+            final DeviceState state = new DeviceState(
+                    MINIMUM_DEVICE_STATE_IDENTIFIER - 1 /* identifier */,
                     null /* name */, 0 /* flags */);
         });
     }
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index c8cbb98..42e3387 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -2077,6 +2077,12 @@
       "group": "WM_DEBUG_LOCKTASK",
       "at": "com\/android\/server\/wm\/LockTaskController.java"
     },
+    "-315778658": {
+      "message": "transferTouchGesture failed because args transferFromToken or transferToToken is null",
+      "level": "ERROR",
+      "group": "WM_DEBUG_EMBEDDED_WINDOWS",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "-312353598": {
       "message": "Executing finish of activity: %s",
       "level": "VERBOSE",
@@ -2293,12 +2299,6 @@
       "group": "WM_DEBUG_ANIM",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "-90559682": {
-      "message": "Config is skipping already pausing %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_CONFIGURATION",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-87705714": {
       "message": "findFocusedWindow: focusedApp=null using new focus @ %s",
       "level": "VERBOSE",
@@ -3547,12 +3547,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1011462000": {
-      "message": "Re-launching after pause: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STATES",
-      "at": "com\/android\/server\/wm\/TaskFragment.java"
-    },
     "1015746067": {
       "message": "Display id=%d is ignoring orientation request for %d, return %d following a per-app override for %s",
       "level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index dffcc6d..b5ea1b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
 import static android.view.WindowManager.TRANSIT_SLEEP;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
 import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
 
@@ -929,7 +930,14 @@
                 Slog.e(TAG, "Duplicate call to finish");
                 return;
             }
-            if (!toHome) {
+
+            boolean returningToApp = !toHome
+                    && !mWillFinishToHome
+                    && mPausingTasks != null
+                    && mState == STATE_NORMAL;
+            if (returningToApp && allAppsAreTranslucent(mPausingTasks)) {
+                mHomeTransitionObserver.notifyHomeVisibilityChanged(true);
+            } else if (!toHome) {
                 // For some transitions, we may have notified home activity that it became visible.
                 // We need to notify the observer that we are no longer going home.
                 mHomeTransitionObserver.notifyHomeVisibilityChanged(false);
@@ -948,7 +956,7 @@
                 if (toHome) wct.reorder(mRecentsTask, true /* toTop */);
                 else wct.restoreTransientOrder(mRecentsTask);
             }
-            if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
+            if (returningToApp) {
                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "  returning to app");
                 // The gesture is returning to the pausing-task(s) rather than continuing with
                 // recents, so end the transition by moving the app back to the top (and also
@@ -1048,6 +1056,18 @@
             }
         }
 
+        private boolean allAppsAreTranslucent(ArrayList<TaskState> tasks) {
+            if (tasks == null || tasks.isEmpty()) {
+                return false;
+            }
+            for (int i = tasks.size() - 1; i >= 0; --i) {
+                if (!tasks.get(i).mIsTranslucent) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
         private void cleanUpPausingOrClosingTask(TaskState task, WindowContainerTransaction wct,
                 SurfaceControl.Transaction finishTransaction, boolean sendUserLeaveHint) {
             if (!sendUserLeaveHint && task.isLeaf()) {
@@ -1118,6 +1138,9 @@
         /** The surface/leash of the task provided by Core. */
         SurfaceControl mTaskSurface;
 
+        /** True when the task is translucent.  */
+        final boolean mIsTranslucent;
+
         /** The (local) animation-leash created for this task. Only non-null for leafs. */
         @Nullable
         SurfaceControl mLeash;
@@ -1126,6 +1149,7 @@
             mToken = change.getContainer();
             mTaskInfo = change.getTaskInfo();
             mTaskSurface = change.getLeash();
+            mIsTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0;
             mLeash = leash;
         }
 
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index ac94a6f..9548525 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3557,6 +3557,36 @@
         }
 
         /**
+         * Set a linear block that contain multiple non-encrypted access unit to this
+         * queue request. Exactly one buffer must be set for a queue request before
+         * calling {@link #queue}. Multiple access units if present must be laid out contiguously
+         * and without gaps and in order. An IllegalArgumentException will be thrown
+         * during {@link #queue} if access units are not laid out contiguously.
+         *
+         * @param block The linear block object
+         * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark
+         *              individual access-unit boundaries and the timestamps associated with it.
+         * @return this object
+         * @throws IllegalStateException if a buffer is already set
+         */
+        @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+        public @NonNull QueueRequest setMultiFrameLinearBlock(
+                @NonNull LinearBlock block,
+                @NonNull ArrayDeque<BufferInfo> infos) {
+            if (!isAccessible()) {
+                throw new IllegalStateException("The request is stale");
+            }
+            if (mLinearBlock != null || mHardwareBuffer != null) {
+                throw new IllegalStateException("Cannot set block twice");
+            }
+            mLinearBlock = block;
+            mBufferInfos.clear();
+            mBufferInfos.addAll(infos);
+            mCryptoInfos.clear();
+            return this;
+        }
+
+        /**
          * Set an encrypted linear block to this queue request. Exactly one buffer must be
          * set for a queue request before calling {@link #queue}. It is possible
          * to use the same {@link LinearBlock} object for multiple queue
@@ -3691,26 +3721,6 @@
         }
 
         /**
-         * Sets MediaCodec.BufferInfo objects describing the access units
-         * contained in this queue request. Access units must be laid out
-         * contiguously without gaps and in order.
-         *
-         * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark
-         *              individual access-unit boundaries and the timestamps associated with it.
-         *              The buffer is expected to contain the data in a continuous manner.
-         * @return this object
-         */
-        @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
-        public @NonNull QueueRequest setBufferInfos(@NonNull ArrayDeque<BufferInfo> infos) {
-            if (!isAccessible()) {
-                throw new IllegalStateException("The request is stale");
-            }
-            mBufferInfos.clear();
-            mBufferInfos.addAll(infos);
-            return this;
-        }
-
-        /**
          * Add an integer parameter.
          * See {@link MediaFormat} for an exhaustive list of supported keys with
          * values of type int, that can also be set with {@link MediaFormat#setInteger}.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3174c37..1e7bc47 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -20,10 +20,12 @@
 import static android.media.Utils.sortDistinctRanges;
 import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS;
 import static android.media.codec.Flags.FLAG_HLG_EDITING;
+import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC;
 import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
 import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
 
 import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -40,6 +42,8 @@
 import android.util.Rational;
 import android.util.Size;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -1808,6 +1812,55 @@
         }
     }
 
+    /** @hide */
+    @IntDef(prefix = {"SECURITY_MODEL_"}, value = {
+        SECURITY_MODEL_SANDBOXED,
+        SECURITY_MODEL_MEMORY_SAFE,
+        SECURITY_MODEL_TRUSTED_CONTENT_ONLY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SecurityModel {}
+
+    /**
+     * In this model the codec is running in a sandboxed process. Even if a
+     * malicious content was fed to the codecs in this model, the impact will
+     * be contained in the sandboxed process.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int SECURITY_MODEL_SANDBOXED = 0;
+    /**
+     * In this model the codec is not running in a sandboxed process, but
+     * written in a memory-safe way. It typically means that the software
+     * implementation of the codec is written in a memory-safe language such
+     * as Rust.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int SECURITY_MODEL_MEMORY_SAFE = 1;
+    /**
+     * In this model the codec is suitable only for trusted content where
+     * the input can be verified to be well-formed and no malicious actor
+     * can alter it. For example, codecs in this model are not suitable
+     * for arbitrary media downloaded from the internet or present in a user
+     * directory. On the other hand, they could be suitable for media encoded
+     * in the backend that the app developer wholly controls.
+     * <p>
+     * Codecs with this security model is not included in
+     * {@link MediaCodecList#REGULAR_CODECS}, but included in
+     * {@link MediaCodecList#ALL_CODECS}.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2;
+
+    /**
+     * Query the security model of the codec.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    @SecurityModel
+    public int getSecurityModel() {
+        // TODO b/297922713 --- detect security model of out-of-sandbox codecs
+        return SECURITY_MODEL_SANDBOXED;
+    }
+
     /**
      * A class that supports querying the video capabilities of a codec.
      */
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 5e40eee..7b83842 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC;
+
 import static com.android.media.codec.flags.Flags.FLAG_CODEC_IMPORTANCE;
 import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
 
@@ -1715,6 +1717,58 @@
     @FlaggedApi(FLAG_CODEC_IMPORTANCE)
     public static final String KEY_IMPORTANCE = "importance";
 
+    /** @hide */
+    @IntDef(flag = true, prefix = {"FLAG_SECURITY_MODEL_"}, value = {
+        FLAG_SECURITY_MODEL_SANDBOXED,
+        FLAG_SECURITY_MODEL_MEMORY_SAFE,
+        FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SecurityModelFlag {}
+
+    /**
+     * Flag for {@link MediaCodecInfo#SECURITY_MODEL_SANDBOXED}.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int FLAG_SECURITY_MODEL_SANDBOXED =
+            (1 << MediaCodecInfo.SECURITY_MODEL_SANDBOXED);
+    /**
+     * Flag for {@link MediaCodecInfo#SECURITY_MODEL_MEMORY_SAFE}.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE =
+            (1 << MediaCodecInfo.SECURITY_MODEL_MEMORY_SAFE);
+    /**
+     * Flag for {@link MediaCodecInfo#SECURITY_MODEL_TRUSTED_CONTENT_ONLY}.
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY =
+            (1 << MediaCodecInfo.SECURITY_MODEL_TRUSTED_CONTENT_ONLY);
+
+    /**
+     * A key describing the requested security model as flags.
+     * <p>
+     * The associated value is a flag of the following values:
+     * {@link FLAG_SECURITY_MODEL_SANDBOXED},
+     * {@link FLAG_SECURITY_MODEL_MEMORY_SAFE},
+     * {@link FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. The default value is
+     * {@link FLAG_SECURITY_MODEL_SANDBOXED}.
+     * <p>
+     * When passed to {@link MediaCodecList#findDecoderForFormat} or
+     * {@link MediaCodecList#findEncoderForFormat}, MediaCodecList filters
+     * the security model of the codecs according to this flag value.
+     * <p>
+     * When passed to {@link MediaCodec#configure}, MediaCodec verifies
+     * the security model matches the flag value passed, and throws
+     * {@link java.lang.IllegalArgumentException} if the model does not match.
+     * <p>
+     * @see MediaCodecInfo#getSecurityModel
+     * @see MediaCodecList#findDecoderForFormat
+     * @see MediaCodecList#findEncoderForFormat
+     */
+    @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+    public static final String KEY_SECURITY_MODEL = "security-model";
+
     /* package private */ MediaFormat(@NonNull Map<String, Object> map) {
         mMap = map;
     }
diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3254a39..f264b16 100644
--- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -44,6 +44,8 @@
 import android.util.Xml;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -138,6 +140,11 @@
     private boolean mCategoryOtherServiceEnabled;
 
     /**
+     * Whether the NFC stack should default to Observe Mode when this preferred service.
+     */
+    private boolean mDefaultToObserveMode;
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
@@ -257,6 +264,9 @@
                         com.android.internal.R.styleable.HostApduService_settingsActivity);
                 mOffHostName = null;
                 mStaticOffHostName = mOffHostName;
+                mDefaultToObserveMode = sa.getBoolean(
+                        R.styleable.HostApduService_defaultToObserveMode,
+                        false);
                 sa.recycle();
             } else {
                 TypedArray sa = res.obtainAttributes(attrs,
@@ -276,6 +286,9 @@
                         com.android.internal.R.styleable.HostApduService_settingsActivity);
                 mOffHostName = sa.getString(
                         com.android.internal.R.styleable.OffHostApduService_secureElementName);
+                mDefaultToObserveMode = sa.getBoolean(
+                        R.styleable.HostApduService_defaultToObserveMode,
+                        false);
                 if (mOffHostName != null) {
                     if (mOffHostName.equals("eSE")) {
                         mOffHostName = "eSE1";
@@ -611,6 +624,25 @@
     }
 
     /**
+     * Returns whether the NFC stack should default to observe mode when this servise is preferred.
+     * @return whether the NFC stack should default to observe mode when this servise is preferred
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public boolean defaultToObserveMode() {
+        return mDefaultToObserveMode;
+    }
+
+    /**
+     * Sets whether the NFC stack should default to observe mode when this servise is preferred.
+     * @param defaultToObserveMode whether the NFC stack should default to observe mode when this
+     *                             servise is preferred
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public void setDefaultToObserveMode(boolean defaultToObserveMode) {
+        mDefaultToObserveMode = defaultToObserveMode;
+    }
+
+    /**
      * Returns description of service.
      * @return user readable description of service
      */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectView.kt
new file mode 100644
index 0000000..aad593e
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectView.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.surfaceeffects.loadingeffect
+
+import android.content.Context
+import android.graphics.BlendMode
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+
+/** Custom View for drawing the [LoadingEffect] with [Canvas.drawPaint]. */
+open class LoadingEffectView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+
+    private var paint: Paint? = null
+    private var blendMode: BlendMode = BlendMode.SRC_OVER
+
+    override fun onDraw(canvas: Canvas) {
+        if (!canvas.isHardwareAccelerated) {
+            return
+        }
+        paint?.let { canvas.drawPaint(it) }
+    }
+
+    /** Designed to be called on [LoadingEffect.PaintDrawCallback.onDraw]. */
+    fun draw(paint: Paint) {
+        this.paint = paint
+        this.paint!!.blendMode = blendMode
+
+        invalidate()
+    }
+
+    /** Sets the blend mode of the [Paint]. */
+    fun setBlendMode(blendMode: BlendMode) {
+        this.blendMode = blendMode
+    }
+}
diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml
index 5db9eee..109e63c 100644
--- a/packages/SystemUI/res/layout/media_session_view.xml
+++ b/packages/SystemUI/res/layout/media_session_view.xml
@@ -67,6 +67,18 @@
         android:background="@drawable/qs_media_outline_layout_bg"
         />
 
+    <com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
+        android:id="@+id/loading_effect_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_expanded"
+        app:layout_constraintStart_toStartOf="@id/album_art"
+        app:layout_constraintEnd_toEndOf="@id/album_art"
+        app:layout_constraintTop_toTopOf="@id/album_art"
+        app:layout_constraintBottom_toBottomOf="@id/album_art"
+        android:clipToOutline="true"
+        android:background="@drawable/qs_media_outline_layout_bg"
+        />
+
     <!-- Guideline for output switcher -->
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/center_vertical_guideline"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e401c71..57c4230 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1416,6 +1416,9 @@
     <!-- Indication on the keyguard that appears when a trust agents unlocks the device. [CHAR LIMIT=40] -->
     <string name="keyguard_indication_trust_unlocked">Kept unlocked by TrustAgent</string>
 
+    <!-- Message asking the user to authenticate with primary authentication methods (PIN/pattern/password) or biometrics after the device is locked by adaptive auth. [CHAR LIMIT=60] -->
+    <string name="kg_prompt_after_adaptive_auth_lock">Theft protection\nDevice locked, too many unlock attempts</string>
+
     <!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] -->
     <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
 
diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml
index c053b33..2f2b10f 100644
--- a/packages/SystemUI/res/xml/media_session_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_session_collapsed.xml
@@ -55,6 +55,15 @@
         app:layout_constraintBottom_toBottomOf="@+id/album_art" />
 
     <Constraint
+        android:id="@+id/loading_effect_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_collapsed"
+        app:layout_constraintStart_toStartOf="@+id/album_art"
+        app:layout_constraintEnd_toEndOf="@+id/album_art"
+        app:layout_constraintTop_toTopOf="@+id/album_art"
+        app:layout_constraintBottom_toBottomOf="@+id/album_art" />
+
+    <Constraint
         android:id="@+id/header_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index 8bf7560d..0140d52 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -48,6 +48,15 @@
         app:layout_constraintBottom_toBottomOf="@+id/album_art" />
 
     <Constraint
+        android:id="@+id/loading_effect_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_expanded"
+        app:layout_constraintStart_toStartOf="@+id/album_art"
+        app:layout_constraintEnd_toEndOf="@+id/album_art"
+        app:layout_constraintTop_toTopOf="@+id/album_art"
+        app:layout_constraintBottom_toBottomOf="@+id/album_art" />
+
+    <Constraint
         android:id="@+id/header_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 3585feb..84c8ea7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -19,6 +19,7 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.view.WindowInsets.Type.ime;
 
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
@@ -126,6 +127,8 @@
                 return R.string.kg_prompt_reason_timeout_password;
             case PROMPT_REASON_TRUSTAGENT_EXPIRED:
                 return R.string.kg_prompt_reason_timeout_password;
+            case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+                return R.string.kg_prompt_after_adaptive_auth_lock;
             case PROMPT_REASON_NONE:
                 return 0;
             default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index db7ff88..bf8900d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -331,6 +331,9 @@
             case PROMPT_REASON_TRUSTAGENT_EXPIRED:
                 resId = R.string.kg_prompt_reason_timeout_pattern;
                 break;
+            case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+                resId = R.string.kg_prompt_after_adaptive_auth_lock;
+                break;
             case PROMPT_REASON_NONE:
                 break;
             default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index fcff0db..bcab6f0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
@@ -138,6 +139,8 @@
                 return R.string.kg_prompt_reason_timeout_pin;
             case PROMPT_REASON_TRUSTAGENT_EXPIRED:
                 return R.string.kg_prompt_reason_timeout_pin;
+            case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+                return R.string.kg_prompt_after_adaptive_auth_lock;
             case PROMPT_REASON_NONE:
                 return 0;
             default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 83b1a2c..3e87c1b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -67,6 +67,11 @@
     int PROMPT_REASON_TRUSTAGENT_EXPIRED = 8;
 
     /**
+     * Some auth is required because adaptive auth has determined risk
+     */
+    int PROMPT_REASON_ADAPTIVE_AUTH_REQUEST = 9;
+
+    /**
      * Strong auth is required because the device has just booted because of an automatic
      * mainline update.
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 536f3af..5d073f1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -35,6 +35,7 @@
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
 import static android.os.BatteryManager.CHARGING_POLICY_DEFAULT;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -1570,6 +1571,14 @@
         return isEncrypted || isLockDown;
     }
 
+    /**
+     * Whether the device is locked by adaptive auth
+     */
+    public boolean isDeviceLockedByAdaptiveAuth(int userId) {
+        return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId),
+                SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST);
+    }
+
     private boolean containsFlag(int haystack, int needle) {
         return (haystack & needle) != 0;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 7b4be02..9c28f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -115,17 +115,11 @@
     }
 
     private var overlayView: View? = null
-    private var lottie: LottieAnimationView? = null
 
     /** Show the side fingerprint sensor indicator */
     private fun show() {
-        overlayView?.let {
-            if (it.isAttachedToWindow) {
-                lottie = it.requireViewById<LottieAnimationView>(R.id.sidefps_animation)
-                lottie?.pauseAnimation()
-                lottie?.removeAllLottieOnCompositionLoadedListener()
-                windowManager.get().removeView(it)
-            }
+        if (overlayView?.isAttachedToWindow == true) {
+            return
         }
 
         overlayView = layoutInflater.get().inflate(R.layout.sidefps_view, null, false)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index 8197145..c25e748 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -50,6 +50,7 @@
 import com.android.systemui.res.R.string.kg_primary_auth_locked_out_password
 import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pattern
 import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pin
+import com.android.systemui.res.R.string.kg_prompt_after_adaptive_auth_lock
 import com.android.systemui.res.R.string.kg_prompt_after_dpm_lock
 import com.android.systemui.res.R.string.kg_prompt_after_update_password
 import com.android.systemui.res.R.string.kg_prompt_after_update_pattern
@@ -208,6 +209,11 @@
                     } else {
                         faceLockedOut(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
                     }
+                } else if (flags.isSomeAuthRequiredAfterAdaptiveAuthRequest) {
+                    authRequiredAfterAdaptiveAuthRequest(
+                        currentSecurityMode,
+                        isFingerprintAuthCurrentlyAllowed.value
+                    )
                 } else if (
                     trustOrBiometricsAvailable &&
                         flags.strongerAuthRequiredAfterNonStrongBiometricsTimeout
@@ -464,6 +470,34 @@
     }.toMessage()
 }
 
+private fun authRequiredAfterAdaptiveAuthRequest(
+    securityMode: SecurityMode,
+    fpAuthIsAllowed: Boolean
+): BouncerMessageModel {
+    return if (fpAuthIsAllowed) authRequiredAfterAdaptiveAuthRequestFingerprintAllowed(securityMode)
+    else
+        return when (securityMode) {
+            SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_adaptive_auth_lock)
+            SecurityMode.Password ->
+                Pair(keyguard_enter_password, kg_prompt_after_adaptive_auth_lock)
+            SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_adaptive_auth_lock)
+            else -> Pair(0, 0)
+        }.toMessage()
+}
+
+private fun authRequiredAfterAdaptiveAuthRequestFingerprintAllowed(
+    securityMode: SecurityMode
+): BouncerMessageModel {
+    return when (securityMode) {
+        SecurityMode.Pattern ->
+            Pair(kg_unlock_with_pattern_or_fp, kg_prompt_after_adaptive_auth_lock)
+        SecurityMode.Password ->
+            Pair(kg_unlock_with_password_or_fp, kg_prompt_after_adaptive_auth_lock)
+        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_after_adaptive_auth_lock)
+        else -> Pair(0, 0)
+    }.toMessage()
+}
+
 private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): BouncerMessageModel {
     return when (securityMode) {
         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index e23ec89..00ec1a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -404,6 +404,7 @@
     public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE = 11;
     public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP = 12;
     public static final int INDICATION_IS_DISMISSIBLE = 13;
+    public static final int INDICATION_TYPE_ADAPTIVE_AUTH = 14;
 
     @IntDef({
             INDICATION_TYPE_NONE,
@@ -419,7 +420,8 @@
             INDICATION_TYPE_REVERSE_CHARGING,
             INDICATION_TYPE_BIOMETRIC_MESSAGE,
             INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
-            INDICATION_IS_DISMISSIBLE
+            INDICATION_IS_DISMISSIBLE,
+            INDICATION_TYPE_ADAPTIVE_AUTH
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface IndicationType{}
@@ -455,6 +457,8 @@
                 return "biometric_message";
             case INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP:
                 return "biometric_message_followup";
+            case INDICATION_TYPE_ADAPTIVE_AUTH:
+                return "adaptive_auth";
             default:
                 return "unknown[" + type + "]";
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 63fd608..641b967 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -30,6 +30,7 @@
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_OCCLUSION;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -920,15 +921,17 @@
                 return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
             } else if ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
+            } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
+                    || mUpdateMonitor.isFingerprintLockedOut())) {
+                return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
+            } else if ((strongAuth & SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
             } else if (trustAgentsEnabled
                     && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
             } else if (trustAgentsEnabled
                     && (strongAuth & SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
-            } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
-                    || mUpdateMonitor.isFingerprintLockedOut())) {
-                return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
             } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
             } else if (any && (strongAuth
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
index cf5b88f..08904b6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
@@ -60,6 +60,12 @@
             LockPatternUtils.StrongAuthTracker
                 .STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
         )
+
+    val isSomeAuthRequiredAfterAdaptiveAuthRequest =
+        containsFlag(
+            flag,
+            LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST
+        )
 }
 
 private fun containsFlag(haystack: Int, needle: Int): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
index 1b14f75..898eacf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
@@ -25,8 +25,9 @@
 import android.widget.TextView
 import androidx.constraintlayout.widget.Barrier
 import com.android.internal.widget.CachingIconView
-import com.android.systemui.res.R
 import com.android.systemui.media.controls.models.GutsViewHolder
+import com.android.systemui.res.R
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
 import com.android.systemui.surfaceeffects.ripple.MultiRippleView
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
 import com.android.systemui.util.animation.TransitionLayout
@@ -42,6 +43,7 @@
     val multiRippleView = itemView.requireViewById<MultiRippleView>(R.id.touch_ripple_view)
     val turbulenceNoiseView =
         itemView.requireViewById<TurbulenceNoiseView>(R.id.turbulence_noise_view)
+    val loadingEffectView = itemView.requireViewById<LoadingEffectView>(R.id.loading_effect_view)
     val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
     val titleText = itemView.requireViewById<TextView>(R.id.header_title)
     val artistText = itemView.requireViewById<TextView>(R.id.header_artist)
@@ -171,6 +173,7 @@
             setOf(
                 R.id.album_art,
                 R.id.turbulence_noise_view,
+                R.id.loading_effect_view,
                 R.id.touch_ripple_view,
             )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index c87fd14..952f9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -29,6 +29,7 @@
 import com.android.settingslib.Utils
 import com.android.systemui.media.controls.models.player.MediaViewHolder
 import com.android.systemui.monet.ColorScheme
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect
 import com.android.systemui.surfaceeffects.ripple.MultiRippleController
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController
 
@@ -118,6 +119,7 @@
         turbulenceNoiseController,
         ::AnimatingColorTransition
     )
+    var loadingEffect: LoadingEffect? = null
 
     val bgColor = context.getColor(com.google.android.material.R.color.material_dynamic_neutral20)
     val surfaceColor =
@@ -128,7 +130,6 @@
             mediaViewHolder.albumView.backgroundTintList = colorList
             mediaViewHolder.gutsViewHolder.setSurfaceColor(surfaceColor)
         }
-
     val accentPrimary =
         animatingColorTransitionFactory(
             loadDefaultColor(R.attr.textColorPrimary),
@@ -139,6 +140,7 @@
             mediaViewHolder.gutsViewHolder.setAccentPrimaryColor(accentPrimary)
             multiRippleController.updateColor(accentPrimary)
             turbulenceNoiseController.updateNoiseColor(accentPrimary)
+            loadingEffect?.updateColor(accentPrimary)
         }
 
     val accentSecondary =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index aa92814..e97c9d3d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -41,6 +41,7 @@
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Matrix;
+import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.BitmapDrawable;
@@ -81,6 +82,7 @@
 import com.android.internal.widget.CachingIconView;
 import com.android.settingslib.widget.AdaptiveIcon;
 import com.android.systemui.ActivityIntentHelper;
+import com.android.systemui.Flags;
 import com.android.systemui.animation.ActivityTransitionAnimator;
 import com.android.systemui.animation.GhostedViewTransitionAnimatorController;
 import com.android.systemui.bluetooth.BroadcastDialogController;
@@ -111,6 +113,9 @@
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect;
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState;
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleController;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleView;
 import com.android.systemui.surfaceeffects.ripple.RippleAnimation;
@@ -248,13 +253,34 @@
     private String mCurrentBroadcastApp;
     private MultiRippleController mMultiRippleController;
     private TurbulenceNoiseController mTurbulenceNoiseController;
+    private LoadingEffect mLoadingEffect;
     private final GlobalSettings mGlobalSettings;
-
+    private final Random mRandom = new Random();
     private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
     private boolean mWasPlaying = false;
     private boolean mButtonClicked = false;
 
-    private final Random mRandom = new Random();
+    private final LoadingEffect.Companion.PaintDrawCallback mNoiseDrawCallback =
+            new LoadingEffect.Companion.PaintDrawCallback() {
+                @Override
+                public void onDraw(@NonNull Paint loadingPaint) {
+                    mMediaViewHolder.getLoadingEffectView().draw(loadingPaint);
+                }
+            };
+    private final LoadingEffect.Companion.AnimationStateChangedCallback mStateChangedCallback =
+            new LoadingEffect.Companion.AnimationStateChangedCallback() {
+                @Override
+                public void onStateChanged(@NonNull AnimationState oldState,
+                        @NonNull AnimationState newState) {
+                    LoadingEffectView loadingEffectView =
+                            mMediaViewHolder.getLoadingEffectView();
+                    if (newState == AnimationState.NOT_PLAYING) {
+                        loadingEffectView.setVisibility(View.INVISIBLE);
+                    } else {
+                        loadingEffectView.setVisibility(View.VISIBLE);
+                    }
+                }
+            };
 
     /**
      * Initialize a new control panel
@@ -456,6 +482,10 @@
 
         TurbulenceNoiseView turbulenceNoiseView = vh.getTurbulenceNoiseView();
         turbulenceNoiseView.setBlendMode(BlendMode.SCREEN);
+        LoadingEffectView loadingEffectView = vh.getLoadingEffectView();
+        loadingEffectView.setBlendMode(BlendMode.SCREEN);
+        loadingEffectView.setVisibility(View.INVISIBLE);
+
         mTurbulenceNoiseController = new TurbulenceNoiseController(turbulenceNoiseView);
 
         mColorSchemeTransition = new ColorSchemeTransition(
@@ -587,22 +617,41 @@
             }
         }
 
-        // Turbulence noise
         if (shouldPlayTurbulenceNoise()) {
+            // Need to create the config here to get the correct view size and color.
             if (mTurbulenceNoiseAnimationConfig == null) {
                 mTurbulenceNoiseAnimationConfig =
-                        createTurbulenceNoiseAnimation();
+                        createTurbulenceNoiseConfig();
             }
-            // Color will be correctly updated in ColorSchemeTransition.
-            mTurbulenceNoiseController.play(
-                    Type.SIMPLEX_NOISE,
-                    mTurbulenceNoiseAnimationConfig
-            );
-            mMainExecutor.executeDelayed(
-                    mTurbulenceNoiseController::finish,
-                    TURBULENCE_NOISE_PLAY_DURATION
-            );
+
+            if (Flags.shaderlibLoadingEffectRefactor()) {
+                if (mLoadingEffect == null) {
+                    mLoadingEffect = new LoadingEffect(
+                            Type.SIMPLEX_NOISE,
+                            mTurbulenceNoiseAnimationConfig,
+                            mNoiseDrawCallback,
+                            mStateChangedCallback
+                    );
+                    mColorSchemeTransition.setLoadingEffect(mLoadingEffect);
+                }
+
+                mLoadingEffect.play();
+                mMainExecutor.executeDelayed(
+                        mLoadingEffect::finish,
+                        TURBULENCE_NOISE_PLAY_DURATION
+                );
+            } else {
+                mTurbulenceNoiseController.play(
+                        Type.SIMPLEX_NOISE,
+                        mTurbulenceNoiseAnimationConfig
+                );
+                mMainExecutor.executeDelayed(
+                        mTurbulenceNoiseController::finish,
+                        TURBULENCE_NOISE_PLAY_DURATION
+                );
+            }
         }
+
         mButtonClicked = false;
         mWasPlaying = isPlaying();
 
@@ -1232,7 +1281,13 @@
         return mButtonClicked && !mWasPlaying && isPlaying();
     }
 
-    private TurbulenceNoiseAnimationConfig createTurbulenceNoiseAnimation() {
+    private TurbulenceNoiseAnimationConfig createTurbulenceNoiseConfig() {
+        View targetView = Flags.shaderlibLoadingEffectRefactor()
+                ? mMediaViewHolder.getLoadingEffectView() :
+                mMediaViewHolder.getTurbulenceNoiseView();
+        int width = targetView.getWidth();
+        int height = targetView.getHeight();
+
         return new TurbulenceNoiseAnimationConfig(
                 /* gridCount= */ 2.14f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
@@ -1242,10 +1297,11 @@
                 /* noiseMoveSpeedX= */ 0.42f,
                 /* noiseMoveSpeedY= */ 0f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
+                // Color will be correctly updated in ColorSchemeTransition.
                 /* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
                 /* backgroundColor= */ Color.BLACK,
-                /* width= */ mMediaViewHolder.getTurbulenceNoiseView().getWidth(),
-                /* height= */ mMediaViewHolder.getTurbulenceNoiseView().getHeight(),
+                width,
+                height,
                 TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
                 /* easeInDuration= */ 1350f,
                 /* easeOutDuration= */ 1350f,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 092f1ed..152f193 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -44,6 +44,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.settingslib.applications.InterestingConfigChanges;
@@ -89,7 +90,16 @@
     private final TaskbarDelegate mTaskbarDelegate;
     private final NavBarHelper mNavBarHelper;
     private int mNavMode;
+    /**
+     * Indicates whether the active display is a large screen, e.g. tablets, foldable devices in
+     * the unfolded state.
+     */
     @VisibleForTesting boolean mIsLargeScreen;
+    /**
+     * Indicates whether the device is a phone, rather than everything else (e.g. foldables,
+     * tablets) is considered not a handheld device.
+     */
+    @VisibleForTesting boolean mIsPhone;
 
     /** A displayId - nav bar maps. */
     @VisibleForTesting
@@ -139,6 +149,8 @@
                 dumpManager, autoHideController, lightBarController, pipOptional,
                 backAnimation.orElse(null), taskStackChangeListeners);
         mIsLargeScreen = isLargeScreen(mContext);
+        mIsPhone =
+                mContext.getResources().getIntArray(R.array.config_foldedDeviceStates).length == 0;
         dumpManager.registerDumpable(this);
     }
 
@@ -253,9 +265,8 @@
 
     /** @return {@code true} if taskbar is enabled, false otherwise */
     private boolean initializeTaskbarIfNecessary() {
-        // Enable for large screens or (phone AND flag is set); assuming phone = !mIsLargeScreen
-        boolean taskbarEnabled = (mIsLargeScreen || enableTaskbarNavbarUnification())
-                && shouldCreateNavBarAndTaskBar(mContext.getDisplayId());
+        boolean taskbarEnabled = supportsTaskbar() && shouldCreateNavBarAndTaskBar(
+                mContext.getDisplayId());
 
         if (taskbarEnabled) {
             Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary");
@@ -274,6 +285,12 @@
         return taskbarEnabled;
     }
 
+    @VisibleForTesting
+    boolean supportsTaskbar() {
+        // Enable for tablets, unfolded state on a foldable device or (non handheld AND flag is set)
+        return mIsLargeScreen || (!mIsPhone && enableTaskbarNavbarUnification());
+    }
+
     private final CommandQueue.Callbacks mCommandQueueCallbacks = new CommandQueue.Callbacks() {
         @Override
         public void onDisplayRemoved(int displayId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 14230ba..19fe60a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import static android.adaptiveauth.Flags.enableAdaptiveAuth;
 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
 import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
@@ -32,6 +33,7 @@
 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_IS_DISMISSIBLE;
+import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ADAPTIVE_AUTH;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
@@ -454,6 +456,9 @@
         updateLockScreenAlignmentMsg();
         updateLockScreenLogoutView();
         updateLockScreenPersistentUnlockMsg();
+        if (enableAdaptiveAuth()) {
+            updateLockScreenAdaptiveAuthMsg(userId);
+        }
     }
 
     private void updateOrganizedOwnedDevice() {
@@ -740,6 +745,22 @@
         }
     }
 
+    private void updateLockScreenAdaptiveAuthMsg(int userId) {
+        final boolean deviceLocked = mKeyguardUpdateMonitor.isDeviceLockedByAdaptiveAuth(userId);
+        if (deviceLocked) {
+            mRotateTextViewController.updateIndication(
+                    INDICATION_TYPE_ADAPTIVE_AUTH,
+                    new KeyguardIndication.Builder()
+                            .setMessage(mContext
+                                    .getString(R.string.kg_prompt_after_adaptive_auth_lock))
+                            .setTextColor(mInitialTextColorState)
+                            .build(),
+                    true);
+        } else {
+            mRotateTextViewController.hideIndication(INDICATION_TYPE_ADAPTIVE_AUTH);
+        }
+    }
+
     private boolean isOrganizationOwnedDevice() {
         return mDevicePolicyManager.isDeviceManaged()
                 || mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 2a4753d..9916ef6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -749,7 +749,7 @@
                 || isNotifUserRedacted;
 
         boolean notificationRequestsRedaction =
-                ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+                ent.isNotificationVisibilityPrivate();
         boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
 
         if (keyguardPrivateNotifications()) {
@@ -767,9 +767,7 @@
         }
         NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
         if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
-            return entry != null && entry.getRanking().getChannel() != null
-                    && entry.getRanking().getChannel().getLockscreenVisibility()
-                    == Notification.VISIBILITY_PRIVATE;
+            return entry != null && entry.isChannelVisibilityPrivate();
         } else {
             return entry != null
                     && entry.getRanking().getLockscreenVisibilityOverride()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8678f0a..e111525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -998,6 +998,23 @@
         return style == null ? "nostyle" : style.getSimpleName();
     }
 
+    /**
+     * Return {@code true} if notification's visibility is {@link Notification.VISIBILITY_PRIVATE}
+     */
+    public boolean isNotificationVisibilityPrivate() {
+        return getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+    }
+
+    /**
+     * Return {@code true} if notification's channel lockscreen visibility is
+     * {@link Notification.VISIBILITY_PRIVATE}
+     */
+    public boolean isChannelVisibilityPrivate() {
+        return getRanking().getChannel() != null
+                && getRanking().getChannel().getLockscreenVisibility()
+                == Notification.VISIBILITY_PRIVATE;
+    }
+
     /** Information about a suggestion that is being edited. */
     public static class EditedSuggestionInfo {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
index 2b0a92c..6956a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
@@ -221,10 +221,15 @@
         // Exempt foreground service notifications from protection in effort to keep screen share
         // stop actions easily accessible
         StatusBarNotification sbn = entry.getSbn();
-        if (sbn.getNotification().isFgsOrUij()) {
-            return !sbn.getPackageName().equals(projection.getPackageName());
+        if (sbn.getNotification().isFgsOrUij()
+                && sbn.getPackageName().equals(projection.getPackageName())) {
+            return false;
         }
 
-        return true;
+        // Only protect/redact notifications if the developer has not explicitly set notification
+        // visibility as public and users has not adjusted default channel visibility to private
+        boolean notificationRequestsRedaction = entry.isNotificationVisibilityPrivate();
+        boolean userForcesRedaction = entry.isChannelVisibilityPrivate();
+        return notificationRequestsRedaction || userForcesRedaction;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 2732047..0957748 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -21,6 +21,7 @@
 import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT;
 import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
@@ -650,6 +651,25 @@
     }
 
     @Test
+    public void testBouncerPrompt_deviceLockedByAdaptiveAuth() {
+        // GIVEN no trust agents enabled and biometrics aren't enrolled
+        when(mUpdateMonitor.isTrustUsuallyManaged(anyInt())).thenReturn(false);
+        when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(false);
+
+        // WHEN the strong auth reason is SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST
+        KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+                mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+        when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+        when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+        when(strongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+                SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST);
+
+        // THEN the bouncer prompt reason should return PROMPT_REASON_ADAPTIVE_AUTH_REQUEST
+        assertEquals(KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST,
+                mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+    }
+
+    @Test
     public void testBouncerPrompt_deviceRestartedDueToMainlineUpdate() {
         // GIVEN biometrics enrolled
         when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index 5996502..c896486 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -40,6 +40,7 @@
 import android.media.session.MediaSession
 import android.media.session.PlaybackState
 import android.os.Bundle
+import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
 import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
 import android.testing.AndroidTestingRunner
@@ -61,6 +62,7 @@
 import com.android.internal.logging.InstanceId
 import com.android.internal.widget.CachingIconView
 import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.bluetooth.BroadcastDialogController
 import com.android.systemui.broadcast.BroadcastSender
@@ -88,6 +90,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
 import com.android.systemui.surfaceeffects.ripple.MultiRippleView
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
@@ -190,6 +193,7 @@
     private lateinit var dismissText: TextView
     private lateinit var multiRippleView: MultiRippleView
     private lateinit var turbulenceNoiseView: TurbulenceNoiseView
+    private lateinit var loadingEffectView: LoadingEffectView
 
     private lateinit var session: MediaSession
     private lateinit var device: MediaDeviceData
@@ -402,6 +406,7 @@
 
         multiRippleView = MultiRippleView(context, null)
         turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        loadingEffectView = LoadingEffectView(context, null)
 
         whenever(viewHolder.player).thenReturn(view)
         whenever(viewHolder.appIcon).thenReturn(appIcon)
@@ -447,6 +452,7 @@
 
         whenever(viewHolder.multiRippleView).thenReturn(multiRippleView)
         whenever(viewHolder.turbulenceNoiseView).thenReturn(turbulenceNoiseView)
+        whenever(viewHolder.loadingEffectView).thenReturn(loadingEffectView)
     }
 
     /** Initialize elements for the recommendation view holder */
@@ -2429,6 +2435,7 @@
 
         mainExecutor.execute {
             assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
+            assertThat(loadingEffectView.visibility).isEqualTo(View.INVISIBLE)
 
             clock.advanceTime(
                 MediaControlPanel.TURBULENCE_NOISE_PLAY_DURATION +
@@ -2436,6 +2443,40 @@
             )
 
             assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+            assertThat(loadingEffectView.visibility).isEqualTo(View.INVISIBLE)
+        }
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_SHADERLIB_LOADING_EFFECT_REFACTOR)
+    fun playTurbulenceNoise_newLoadingEffect_finishesAfterDuration() {
+        val semanticActions =
+            MediaButton(
+                playOrPause =
+                    MediaAction(
+                        icon = null,
+                        action = {},
+                        contentDescription = "play",
+                        background = null
+                    )
+            )
+        val data = mediaData.copy(semanticActions = semanticActions)
+        player.attachPlayer(viewHolder)
+        player.bindPlayer(data, KEY)
+
+        viewHolder.actionPlayPause.callOnClick()
+
+        mainExecutor.execute {
+            assertThat(loadingEffectView.visibility).isEqualTo(View.VISIBLE)
+            assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+
+            clock.advanceTime(
+                MediaControlPanel.TURBULENCE_NOISE_PLAY_DURATION +
+                    TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS.toLong()
+            )
+
+            assertThat(loadingEffectView.visibility).isEqualTo(View.INVISIBLE)
+            assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
         }
     }
 
@@ -2458,6 +2499,30 @@
         viewHolder.action0.callOnClick()
 
         assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+        assertThat(loadingEffectView.visibility).isEqualTo(View.INVISIBLE)
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_SHADERLIB_LOADING_EFFECT_REFACTOR)
+    fun playTurbulenceNoise_newLoadingEffect_whenPlaybackStateIsNotPlaying_doesNotPlayTurbulence() {
+        val semanticActions =
+            MediaButton(
+                custom0 =
+                    MediaAction(
+                        icon = null,
+                        action = {},
+                        contentDescription = "custom0",
+                        background = null
+                    ),
+            )
+        val data = mediaData.copy(semanticActions = semanticActions)
+        player.attachPlayer(viewHolder)
+        player.bindPlayer(data, KEY)
+
+        viewHolder.action0.callOnClick()
+
+        assertThat(loadingEffectView.visibility).isEqualTo(View.INVISIBLE)
+        assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
index bfb18c8..52859cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
@@ -22,6 +22,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -289,32 +291,43 @@
         verify(mCommandQueue, never()).addCallback(any(TaskbarDelegate.class));
     }
 
-
     @Test
     public void testConfigurationChange_taskbarNotInitialized() {
         Configuration configuration = mContext.getResources().getConfiguration();
-        when(Utilities.isLargeScreen(any())).thenReturn(true);
+        mNavigationBarController.mIsLargeScreen = true;
         mNavigationBarController.onConfigChanged(configuration);
         verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
     }
 
     @Test
-    public void testConfigurationChangeUnfolding_taskbarInitialized() {
+    public void testConfigurationChange_taskbarInitialized() {
         Configuration configuration = mContext.getResources().getConfiguration();
-        when(Utilities.isLargeScreen(any())).thenReturn(true);
+        mNavigationBarController.mIsLargeScreen = true;
         when(mTaskbarDelegate.isInitialized()).thenReturn(true);
         mNavigationBarController.onConfigChanged(configuration);
         verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
     }
 
     @Test
-    public void testConfigurationChangeFolding_taskbarInitialized() {
+    public void testShouldRenderTaskbar_taskbarNotRenderedOnPhone() {
+        mNavigationBarController.mIsLargeScreen = false;
+        mNavigationBarController.mIsPhone = true;
+        assertFalse(mNavigationBarController.supportsTaskbar());
+    }
+
+    @Test
+    public void testShouldRenderTaskbar_taskbarRenderedOnTabletOrUnfolded() {
+        mNavigationBarController.mIsLargeScreen = true;
+        mNavigationBarController.mIsPhone = false;
+        assertTrue(mNavigationBarController.supportsTaskbar());
+    }
+
+    @Test
+    public void testShouldRenderTaskbar_taskbarRenderedInFoldedState() {
         assumeTrue(enableTaskbarNavbarUnification());
 
-        Configuration configuration = mContext.getResources().getConfiguration();
-        when(Utilities.isLargeScreen(any())).thenReturn(false);
-        when(mTaskbarDelegate.isInitialized()).thenReturn(true);
-        mNavigationBarController.onConfigChanged(configuration);
-        verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
+        mNavigationBarController.mIsLargeScreen = false;
+        mNavigationBarController.mIsPhone = false;
+        assertTrue(mNavigationBarController.supportsTaskbar());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index ccc9dc0..8a48fe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -50,8 +50,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SbnBuilder;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -280,6 +280,66 @@
     }
 
     @Test
+    public void testIsNotificationVisibilityPrivate_true() {
+        assertTrue(mEntry.isNotificationVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsNotificationVisibilityPrivate_visibilityPublic_false() {
+        Notification.Builder notification = new Notification.Builder(mContext, "")
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_NAME)
+                .setOpPkg(TEST_PACKAGE_NAME)
+                .setUid(TEST_UID)
+                .setChannel(mChannel)
+                .setId(mId++)
+                .setNotification(notification.build())
+                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+                .build();
+
+        assertFalse(entry.isNotificationVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_true() {
+        assertTrue(mEntry.isChannelVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_visibilityPublic_false() {
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+        StatusBarNotification sbn = new SbnBuilder().build();
+        Ranking ranking = new RankingBuilder()
+                .setChannel(channel)
+                .setKey(sbn.getKey())
+                .build();
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+        assertFalse(entry.isChannelVisibilityPrivate());
+    }
+
+    @Test
+    public void testIsChannelVisibilityPrivate_entryHasNoChannel_false() {
+        StatusBarNotification sbn = new SbnBuilder().build();
+        Ranking ranking = new RankingBuilder()
+                .setChannel(null)
+                .setKey(sbn.getKey())
+                .build();
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+        assertFalse(entry.isChannelVisibilityPrivate());
+    }
+
+    @Test
     public void notificationDataEntry_testIsLastMessageFromReply() {
         Person.Builder person = new Person.Builder()
                 .setName("name")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
index 1dac642..a2af38f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
@@ -19,17 +19,24 @@
 import android.app.ActivityOptions
 import android.app.IActivityManager
 import android.app.Notification
+import android.app.Notification.FLAG_FOREGROUND_SERVICE
+import android.app.Notification.VISIBILITY_PRIVATE
+import android.app.Notification.VISIBILITY_PUBLIC
+import android.app.NotificationChannel
+import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
 import android.media.projection.MediaProjectionInfo
 import android.media.projection.MediaProjectionManager
 import android.platform.test.annotations.EnableFlags
 import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS
-import android.service.notification.StatusBarNotification
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.server.notification.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.RankingBuilder
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.concurrency.mockExecutorHandler
 import com.android.systemui.util.mockito.whenever
@@ -316,6 +323,25 @@
 
         assertFalse(controller.shouldProtectNotification(notificationEntry))
     }
+    @Test
+    fun shouldProtectNotification_projectionActive_publicNotification_false() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        // App marked notification visibility as public
+        val notificationEntry = setupPublicNotificationEntry(TEST_PROJECTION_PACKAGE_NAME)
+
+        assertFalse(controller.shouldProtectNotification(notificationEntry))
+    }
+
+    @Test
+    fun shouldProtectNotification_projectionActive_publicNotificationUserChannelOverride_true() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        val notificationEntry =
+            setupPublicNotificationEntryWithUserOverriddenChannel(TEST_PROJECTION_PACKAGE_NAME)
+
+        assertTrue(controller.shouldProtectNotification(notificationEntry))
+    }
 
     private fun setDisabledViaDeveloperOption() {
         globalSettings.putInt(DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1)
@@ -336,21 +362,50 @@
 
     private fun setupNotificationEntry(
         packageName: String,
-        isFgs: Boolean = false
+        isFgs: Boolean = false,
+        overrideVisibility: Boolean = false,
+        overrideChannelVisibility: Boolean = false,
     ): NotificationEntry {
-        val notificationEntry = mock(NotificationEntry::class.java)
-        val sbn = mock(StatusBarNotification::class.java)
-        val notification = mock(Notification::class.java)
-        whenever(notificationEntry.sbn).thenReturn(sbn)
-        whenever(sbn.packageName).thenReturn(packageName)
-        whenever(sbn.notification).thenReturn(notification)
-        whenever(notification.isFgsOrUij).thenReturn(isFgs)
-
+        val notification = Notification()
+        if (isFgs) {
+            notification.flags = notification.flags or FLAG_FOREGROUND_SERVICE
+        }
+        if (overrideVisibility) {
+            // Developer has marked notification as public
+            notification.visibility = VISIBILITY_PUBLIC
+        }
+        val notificationEntry =
+            NotificationEntryBuilder().setNotification(notification).setPkg(packageName).build()
+        val channel = NotificationChannel("1", "1", IMPORTANCE_HIGH)
+        if (overrideChannelVisibility) {
+            // User doesn't allow private notifications at the channel level
+            channel.lockscreenVisibility = VISIBILITY_PRIVATE
+        }
+        notificationEntry.setRanking(
+            RankingBuilder(notificationEntry.ranking)
+                .setChannel(channel)
+                .setVisibilityOverride(VISIBILITY_NO_OVERRIDE)
+                .build()
+        )
         return notificationEntry
     }
 
     private fun setupFgsNotificationEntry(packageName: String): NotificationEntry {
-        return setupNotificationEntry(packageName, /* isFgs= */ true)
+        return setupNotificationEntry(packageName, isFgs = true)
+    }
+
+    private fun setupPublicNotificationEntry(packageName: String): NotificationEntry {
+        return setupNotificationEntry(packageName, overrideVisibility = true)
+    }
+
+    private fun setupPublicNotificationEntryWithUserOverriddenChannel(
+        packageName: String
+    ): NotificationEntry {
+        return setupNotificationEntry(
+            packageName,
+            overrideVisibility = true,
+            overrideChannelVisibility = true
+        )
     }
 
     companion object {
diff --git a/ravenwood/run-ravenwood-tests.sh b/ravenwood/run-ravenwood-tests.sh
index 3f4b8a7..259aa70 100755
--- a/ravenwood/run-ravenwood-tests.sh
+++ b/ravenwood/run-ravenwood-tests.sh
@@ -13,10 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Run all the ravenwood tests.
+# Run all the ravenwood tests + hoststubgen unit tests.
+
+all_tests="hoststubgentest tiny-framework-dump-test hoststubgen-invoke-test"
 
 # "echo" is to remove the newlines
-all_tests=$(echo $(${0%/*}/list-ravenwood-tests.sh) )
+all_tests="$all_tests $(echo $(${0%/*}/list-ravenwood-tests.sh) )"
 
 echo "Running tests: $all_tests"
 atest $all_tests
diff --git a/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java b/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java
new file mode 100644
index 0000000..3312be2
--- /dev/null
+++ b/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java
@@ -0,0 +1,238 @@
+/*
+ * 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.adaptiveauth;
+
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.hardware.biometrics.AuthenticationStateListener;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockSettingsStateListener;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.pm.UserManagerInternal;
+import com.android.server.wm.WindowManagerInternal;
+
+import java.util.Objects;
+
+/**
+ * @hide
+ */
+public class AdaptiveAuthService extends SystemService {
+    private static final String TAG = "AdaptiveAuthService";
+    private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
+
+    @VisibleForTesting
+    static final int MAX_ALLOWED_FAILED_AUTH_ATTEMPTS = 5;
+    private static final int MSG_REPORT_PRIMARY_AUTH_ATTEMPT = 1;
+    private static final int MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT = 2;
+    private static final int AUTH_SUCCESS = 1;
+    private static final int AUTH_FAILURE = 0;
+
+    private final LockPatternUtils mLockPatternUtils;
+    private final LockSettingsInternal mLockSettings;
+    private final BiometricManager mBiometricManager;
+    private final KeyguardManager mKeyguardManager;
+    private final PowerManager mPowerManager;
+    private final WindowManagerInternal mWindowManager;
+    private final UserManagerInternal mUserManager;
+    @VisibleForTesting
+    final SparseIntArray mFailedAttemptsForUser = new SparseIntArray();
+
+    public AdaptiveAuthService(Context context) {
+        this(context, new LockPatternUtils(context));
+    }
+
+    @VisibleForTesting
+    public AdaptiveAuthService(Context context, LockPatternUtils lockPatternUtils) {
+        super(context);
+        mLockPatternUtils = lockPatternUtils;
+        mLockSettings = Objects.requireNonNull(
+                LocalServices.getService(LockSettingsInternal.class));
+        mBiometricManager = Objects.requireNonNull(
+                context.getSystemService(BiometricManager.class));
+        mKeyguardManager = Objects.requireNonNull(context.getSystemService(KeyguardManager.class));
+        mPowerManager = Objects.requireNonNull(context.getSystemService(PowerManager.class));
+        mWindowManager = Objects.requireNonNull(
+                LocalServices.getService(WindowManagerInternal.class));
+        mUserManager = Objects.requireNonNull(LocalServices.getService(UserManagerInternal.class));
+    }
+
+    @Override
+    public void onStart() {}
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            init();
+        }
+    }
+
+    @VisibleForTesting
+    void init() {
+        mLockSettings.registerLockSettingsStateListener(mLockSettingsStateListener);
+        mBiometricManager.registerAuthenticationStateListener(mAuthenticationStateListener);
+    }
+
+    private final LockSettingsStateListener mLockSettingsStateListener =
+            new LockSettingsStateListener() {
+                @Override
+                public void onAuthenticationSucceeded(int userId) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "LockSettingsStateListener#onAuthenticationSucceeded");
+                    }
+                    mHandler.obtainMessage(MSG_REPORT_PRIMARY_AUTH_ATTEMPT, AUTH_SUCCESS, userId)
+                            .sendToTarget();
+                }
+
+                @Override
+                public void onAuthenticationFailed(int userId) {
+                    Slog.i(TAG, "LockSettingsStateListener#onAuthenticationFailed");
+                    mHandler.obtainMessage(MSG_REPORT_PRIMARY_AUTH_ATTEMPT, AUTH_FAILURE, userId)
+                            .sendToTarget();
+                }
+            };
+
+    private final AuthenticationStateListener mAuthenticationStateListener =
+            new AuthenticationStateListener.Stub() {
+                @Override
+                public void onAuthenticationStarted(int requestReason) {}
+
+                @Override
+                public void onAuthenticationStopped() {}
+
+                @Override
+                public void onAuthenticationSucceeded(int requestReason, int userId) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "AuthenticationStateListener#onAuthenticationSucceeded");
+                    }
+                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_SUCCESS, userId)
+                            .sendToTarget();
+                }
+
+                @Override
+                public void onAuthenticationFailed(int requestReason, int userId) {
+                    Slog.i(TAG, "AuthenticationStateListener#onAuthenticationFailed");
+                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_FAILURE, userId)
+                            .sendToTarget();
+                }
+
+                @Override
+                public void onAuthenticationAcquired(BiometricSourceType biometricSourceType,
+                        int requestReason, int acquiredInfo) {}
+            };
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REPORT_PRIMARY_AUTH_ATTEMPT:
+                    handleReportPrimaryAuthAttempt(msg.arg1 != AUTH_FAILURE, msg.arg2);
+                    break;
+                case MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT:
+                    handleReportBiometricAuthAttempt(msg.arg1 != AUTH_FAILURE, msg.arg2);
+                    break;
+            }
+        }
+    };
+
+    private void handleReportPrimaryAuthAttempt(boolean success, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "handleReportPrimaryAuthAttempt: success=" + success
+                    + ", userId=" + userId);
+        }
+        reportAuthAttempt(success, userId);
+    }
+
+    private void handleReportBiometricAuthAttempt(boolean success, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "handleReportBiometricAuthAttempt: success=" + success
+                    + ", userId=" + userId);
+        }
+        reportAuthAttempt(success, userId);
+    }
+
+    private void reportAuthAttempt(boolean success, int userId) {
+        if (success) {
+            // Deleting the entry effectively resets the counter of failed attempts for the user
+            mFailedAttemptsForUser.delete(userId);
+            return;
+        }
+
+        final int numFailedAttempts = mFailedAttemptsForUser.get(userId, 0) + 1;
+        Slog.i(TAG, "reportAuthAttempt: numFailedAttempts=" + numFailedAttempts
+                + ", userId=" + userId);
+        mFailedAttemptsForUser.put(userId, numFailedAttempts);
+
+        // Don't lock again if the device is already locked and if Keyguard is already showing and
+        // isn't trivially dismissible
+        if (mKeyguardManager.isDeviceLocked(userId) && mKeyguardManager.isKeyguardLocked()) {
+            Slog.d(TAG, "Not locking the device because the device is already locked.");
+            return;
+        }
+
+        if (numFailedAttempts < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS) {
+            Slog.d(TAG, "Not locking the device because the number of failed attempts is below"
+                    + " the threshold.");
+            return;
+        }
+
+        //TODO: additionally consider the trust signal before locking device
+        lockDevice(userId);
+    }
+
+    /**
+     * Locks the device and requires primary auth or biometric auth for unlocking
+     */
+    private void lockDevice(int userId) {
+        // Require either primary auth or biometric auth to unlock the device again. Keyguard and
+        // bouncer will also check the StrongAuthFlag for the user to display correct strings for
+        // explaining why the device is locked
+        mLockPatternUtils.requireStrongAuth(SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST, userId);
+
+        // If userId is a profile that has a different parent userId (regardless of its profile
+        // type, or whether it's a profile with unified challenges or not), its parent userId that
+        // owns the Keyguard will also be locked
+        final int parentUserId = mUserManager.getProfileParentId(userId);
+        Slog.i(TAG, "lockDevice: userId=" + userId + ", parentUserId=" + parentUserId);
+        if (parentUserId != userId) {
+            mLockPatternUtils.requireStrongAuth(SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST,
+                    parentUserId);
+        }
+
+        // Power off the display
+        mPowerManager.goToSleep(SystemClock.uptimeMillis());
+
+        // Lock the device
+        mWindowManager.lockNow();
+    }
+}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7d82f0c..df46e5d 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -67,7 +68,10 @@
 import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+import static android.media.audio.Flags.foregroundAudioControl;
 import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -2266,6 +2270,15 @@
                             (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
                                     != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
 
+                    if (foregroundAudioControl()) { // flag check
+                        final int fgsAudioType = FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
+                                | FOREGROUND_SERVICE_TYPE_CAMERA
+                                | FOREGROUND_SERVICE_TYPE_MICROPHONE
+                                | FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+                        capabilityFromFGS |= (psr.getForegroundServiceTypes() & fgsAudioType) != 0
+                                ? PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL : 0;
+                    }
+
                     final boolean enabled = state.getCachedCompatChange(
                             CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY);
                     if (enabled) {
diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
index f85b03e..1bf779a 100644
--- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
+++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
@@ -722,14 +722,8 @@
         performNewUpdateOomAdjLSP(oomAdjReason, topApp, targetProcesses, activeUids,
                 fullUpdate, now, UNKNOWN_ADJ);
 
-        if (fullUpdate) {
-            assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
-        } else {
-            activeProcesses.clear();
-            activeProcesses.addAll(targetProcesses);
-            assignCachedAdjIfNecessary(activeProcesses);
-            activeProcesses.clear();
-        }
+        // TODO: b/319163103 - optimize cache adj assignment to not require the whole lru list.
+        assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
         postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime);
         targetProcesses.clear();
 
@@ -996,11 +990,11 @@
                             && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ)
                     || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ
                             && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND
-                            && service.mState.getCurProcState() <= PROCESS_STATE_TOP)) {
+                            && service.mState.getCurProcState() <= PROCESS_STATE_TOP)
+                    || (service.isSdkSandbox && cr.binding.attributedClient != null)) {
                 continue;
             }
 
-
             computeServiceHostOomAdjLSP(cr, service, app, now, topApp, fullUpdate, false, false,
                     oomAdjReason, cachedAdj, false, false);
         }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index d23d9fb..9883f09 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1678,7 +1678,11 @@
                 final ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(j);
                 for (int k = clist.size() - 1; k >= 0; k--) {
                     final ConnectionRecord cr = clist.get(k);
-                    consumer.accept(cr.binding.client);
+                    if (isSdkSandbox && cr.binding.attributedClient != null) {
+                        consumer.accept(cr.binding.attributedClient);
+                    } else {
+                        consumer.accept(cr.binding.client);
+                    }
                 }
             }
         }
@@ -1689,25 +1693,5 @@
                 consumer.accept(conn.client);
             }
         }
-        // If this process is a sandbox itself, also add the app on whose behalf
-        // its running
-        if (isSdkSandbox) {
-            for (int is = mServices.numberOfRunningServices() - 1; is >= 0; is--) {
-                ServiceRecord s = mServices.getRunningServiceAt(is);
-                ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
-                        s.getConnections();
-                for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) {
-                    ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
-                    for (int i = clist.size() - 1; i >= 0; i--) {
-                        ConnectionRecord cr = clist.get(i);
-                        ProcessRecord attributedApp = cr.binding.attributedClient;
-                        if (attributedApp == null || attributedApp == this) {
-                            continue;
-                        }
-                        consumer.accept(attributedApp);
-                    }
-                }
-            }
-        }
     }
 }
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 57d233e..562beaf 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -205,10 +205,10 @@
     }
 
     /**
-     * Returns the FGS typps, but it doesn't tell if the types include "NONE" or not, so
-     * do not use it outside of this class.
+     * Returns the FGS types, but it doesn't tell if the types include "NONE" or not, use
+     * {@link #hasForegroundServices()}
      */
-    private int getForegroundServiceTypes() {
+    int getForegroundServiceTypes() {
         return mHasForegroundServices ? mFgServiceTypes : 0;
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 145b213..fd09ad1 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -166,7 +166,6 @@
 import com.android.server.LocalManagerRegistry;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
-import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemServiceManager;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.pm.PackageList;
@@ -1038,7 +1037,7 @@
                                 new Ops(pkgName, uidState));
                     }
 
-                    createSandboxUidStateIfNotExistsForAppLocked(uid);
+                    createSandboxUidStateIfNotExistsForAppLocked(uid, null);
                 }
             } else if (action.equals(ACTION_PACKAGE_REMOVED) && !intent.hasExtra(EXTRA_REPLACING)) {
                 synchronized (AppOpsService.this) {
@@ -1050,69 +1049,8 @@
                     return;
                 }
 
-                ArrayMap<String, String> dstAttributionTags = new ArrayMap<>();
-                ArraySet<String> attributionTags = new ArraySet<>();
-                attributionTags.add(null);
-                if (pkg.getAttributions() != null) {
-                    int numAttributions = pkg.getAttributions().size();
-                    for (int attributionNum = 0; attributionNum < numAttributions;
-                            attributionNum++) {
-                        ParsedAttribution attribution = pkg.getAttributions().get(attributionNum);
-                        attributionTags.add(attribution.getTag());
-
-                        int numInheritFrom = attribution.getInheritFrom().size();
-                        for (int inheritFromNum = 0; inheritFromNum < numInheritFrom;
-                                inheritFromNum++) {
-                            dstAttributionTags.put(attribution.getInheritFrom().get(inheritFromNum),
-                                    attribution.getTag());
-                        }
-                    }
-                }
-
                 synchronized (AppOpsService.this) {
-                    UidState uidState = mUidStates.get(uid);
-                    if (uidState == null) {
-                        return;
-                    }
-
-                    Ops ops = uidState.pkgOps.get(pkgName);
-                    if (ops == null) {
-                        return;
-                    }
-
-                    // Reset cached package properties to re-initialize when needed
-                    ops.bypass = null;
-                    ops.knownAttributionTags.clear();
-
-                    // Merge data collected for removed attributions into their successor
-                    // attributions
-                    int numOps = ops.size();
-                    for (int opNum = 0; opNum < numOps; opNum++) {
-                        Op op = ops.valueAt(opNum);
-                        for (int deviceIndex = op.mDeviceAttributedOps.size() - 1; deviceIndex >= 0;
-                                deviceIndex--) {
-                            ArrayMap<String, AttributedOp> attributedOps =
-                                    op.mDeviceAttributedOps.valueAt(deviceIndex);
-                            for (int tagIndex = attributedOps.size() - 1; tagIndex >= 0;
-                                    tagIndex--) {
-                                String tag = attributedOps.keyAt(tagIndex);
-                                if (attributionTags.contains(tag)) {
-                                    // attribution still exist after upgrade
-                                    continue;
-                                }
-
-                                String newAttributionTag = dstAttributionTags.get(tag);
-
-                                AttributedOp newAttributedOp = op.getOrCreateAttribution(op,
-                                        newAttributionTag,
-                                        op.mDeviceAttributedOps.keyAt(deviceIndex));
-                                newAttributedOp.add(attributedOps.get(tag));
-                                attributedOps.remove(tag);
-
-                                scheduleFastWriteLocked();
-                            }
-                        }
-                    }
+                    refreshAttributionsLocked(pkg, uid);
                 }
             }
         }
@@ -1136,41 +1074,6 @@
         mContext.registerReceiverAsUser(mOnPackageUpdatedReceiver, UserHandle.ALL,
                 packageUpdateFilter, null, null);
 
-        synchronized (this) {
-            for (int uidNum = mUidStates.size() - 1; uidNum >= 0; uidNum--) {
-                int uid = mUidStates.keyAt(uidNum);
-                UidState uidState = mUidStates.valueAt(uidNum);
-
-                String[] pkgsInUid = getPackagesForUid(uidState.uid);
-                if (ArrayUtils.isEmpty(pkgsInUid) && uid >= Process.FIRST_APPLICATION_UID) {
-                    uidState.clear();
-                    mUidStates.removeAt(uidNum);
-                    scheduleFastWriteLocked();
-                    continue;
-                }
-
-                ArrayMap<String, Ops> pkgs = uidState.pkgOps;
-
-                int numPkgs = pkgs.size();
-                for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
-                    String pkg = pkgs.keyAt(pkgNum);
-
-                    String action;
-                    if (!ArrayUtils.contains(pkgsInUid, pkg)) {
-                        action = ACTION_PACKAGE_REMOVED;
-                    } else {
-                        action = Intent.ACTION_PACKAGE_REPLACED;
-                    }
-
-                    SystemServerInitThreadPool.submit(
-                            () -> mOnPackageUpdatedReceiver.onReceive(mContext, new Intent(action)
-                                    .setData(Uri.fromParts("package", pkg, null))
-                                    .putExtra(Intent.EXTRA_UID, uid)),
-                            "Update app-ops uidState in case package " + pkg + " changed");
-                }
-            }
-        }
-
         prepareInternalCallbacks();
 
         final IntentFilter packageSuspendFilter = new IntentFilter();
@@ -1258,20 +1161,27 @@
     void initializeUidStates() {
         UserManagerInternal umi = getUserManagerInternal();
         synchronized (this) {
+            SparseBooleanArray knownUids = new SparseBooleanArray();
+
+            for (int uid : NON_PACKAGE_UIDS) {
+                if (!mUidStates.contains(uid)) {
+                    mUidStates.put(uid, new UidState(uid));
+                }
+                knownUids.put(uid, true);
+            }
+
             int[] userIds = umi.getUserIds();
             try (PackageManagerLocal.UnfilteredSnapshot snapshot =
                          getPackageManagerLocal().withUnfilteredSnapshot()) {
                 Map<String, PackageState> packageStates = snapshot.getPackageStates();
                 for (int i = 0; i < userIds.length; i++) {
                     int userId = userIds[i];
-                    initializeUserUidStatesLocked(userId, packageStates);
+                    initializeUserUidStatesLocked(userId, packageStates, knownUids);
                 }
-            }
 
-            for (int uid : NON_PACKAGE_UIDS) {
-                mUidStates.put(uid, new UidState(uid));
+                trimUidStatesLocked(knownUids, packageStates);
+                mUidStatesInitialized = true;
             }
-            mUidStatesInitialized = true;
         }
     }
 
@@ -1279,26 +1189,34 @@
         synchronized (this) {
             try (PackageManagerLocal.UnfilteredSnapshot snapshot =
                     getPackageManagerLocal().withUnfilteredSnapshot()) {
-                initializeUserUidStatesLocked(userId, snapshot.getPackageStates());
+                initializeUserUidStatesLocked(userId, snapshot.getPackageStates(), null);
             }
         }
     }
 
     private void initializeUserUidStatesLocked(int userId, Map<String,
-            PackageState> packageStates) {
+            PackageState> packageStates, SparseBooleanArray knownUids) {
         for (Map.Entry<String, PackageState> entry : packageStates.entrySet()) {
-            int appId = entry.getValue().getAppId();
+            PackageState packageState = entry.getValue();
+            if (packageState.isApex()) {
+                continue;
+            }
+            int appId = packageState.getAppId();
             String packageName = entry.getKey();
 
-            initializePackageUidStateLocked(userId, appId, packageName);
+            initializePackageUidStateLocked(userId, appId, packageName, knownUids);
         }
     }
 
     /*
       Be careful not to clear any existing data; only want to add objects that don't already exist.
      */
-    private void initializePackageUidStateLocked(int userId, int appId, String packageName) {
+    private void initializePackageUidStateLocked(int userId, int appId, String packageName,
+            SparseBooleanArray knownUids) {
         int uid = UserHandle.getUid(userId, appId);
+        if (knownUids != null) {
+            knownUids.put(uid, true);
+        }
         UidState uidState = getUidStateLocked(uid, true);
         Ops ops = uidState.pkgOps.get(packageName);
         if (ops == null) {
@@ -1316,7 +1234,105 @@
             }
         }
 
-        createSandboxUidStateIfNotExistsForAppLocked(uid);
+        createSandboxUidStateIfNotExistsForAppLocked(uid, knownUids);
+    }
+
+    private void trimUidStatesLocked(SparseBooleanArray knownUids,
+            Map<String, PackageState> packageStates) {
+        synchronized (this) {
+            // Remove what may have been added during persistence parsing
+            for (int i = mUidStates.size() - 1; i >= 0; i--) {
+                int uid = mUidStates.keyAt(i);
+                if (knownUids.get(uid, false)) {
+                    if (uid >= Process.FIRST_APPLICATION_UID) {
+                        ArrayMap<String, Ops> pkgOps = mUidStates.valueAt(i).pkgOps;
+                        for (int j = 0; j < pkgOps.size(); j++) {
+                            String pkgName = pkgOps.keyAt(j);
+                            if (!packageStates.containsKey(pkgName)) {
+                                pkgOps.removeAt(j);
+                                continue;
+                            }
+                            AndroidPackage pkg = packageStates.get(pkgName).getAndroidPackage();
+                            if (pkg != null) {
+                                refreshAttributionsLocked(pkg, uid);
+                            }
+                        }
+                        if (pkgOps.isEmpty()) {
+                            mUidStates.remove(i);
+                        }
+                    }
+                } else {
+                    mUidStates.removeAt(i);
+                }
+            }
+        }
+    }
+
+    @GuardedBy("this")
+    private void refreshAttributionsLocked(AndroidPackage pkg, int uid) {
+        String pkgName = pkg.getPackageName();
+        ArrayMap<String, String> dstAttributionTags = new ArrayMap<>();
+        ArraySet<String> attributionTags = new ArraySet<>();
+        attributionTags.add(null);
+        if (pkg.getAttributions() != null) {
+            int numAttributions = pkg.getAttributions().size();
+            for (int attributionNum = 0; attributionNum < numAttributions;
+                    attributionNum++) {
+                ParsedAttribution attribution = pkg.getAttributions().get(attributionNum);
+                attributionTags.add(attribution.getTag());
+
+                int numInheritFrom = attribution.getInheritFrom().size();
+                for (int inheritFromNum = 0; inheritFromNum < numInheritFrom;
+                        inheritFromNum++) {
+                    dstAttributionTags.put(attribution.getInheritFrom().get(inheritFromNum),
+                            attribution.getTag());
+                }
+            }
+        }
+
+        UidState uidState = mUidStates.get(uid);
+        if (uidState == null) {
+            return;
+        }
+
+        Ops ops = uidState.pkgOps.get(pkgName);
+        if (ops == null) {
+            return;
+        }
+
+        // Reset cached package properties to re-initialize when needed
+        ops.bypass = null;
+        ops.knownAttributionTags.clear();
+
+        // Merge data collected for removed attributions into their successor
+        // attributions
+        int numOps = ops.size();
+        for (int opNum = 0; opNum < numOps; opNum++) {
+            Op op = ops.valueAt(opNum);
+            for (int deviceIndex = op.mDeviceAttributedOps.size() - 1; deviceIndex >= 0;
+                    deviceIndex--) {
+                ArrayMap<String, AttributedOp> attributedOps =
+                        op.mDeviceAttributedOps.valueAt(deviceIndex);
+                for (int tagIndex = attributedOps.size() - 1; tagIndex >= 0;
+                        tagIndex--) {
+                    String tag = attributedOps.keyAt(tagIndex);
+                    if (attributionTags.contains(tag)) {
+                        // attribution still exist after upgrade
+                        continue;
+                    }
+
+                    String newAttributionTag = dstAttributionTags.get(tag);
+
+                    AttributedOp newAttributedOp = op.getOrCreateAttribution(op,
+                            newAttributionTag,
+                            op.mDeviceAttributedOps.keyAt(deviceIndex));
+                    newAttributedOp.add(attributedOps.get(tag));
+                    attributedOps.remove(tag);
+
+                    scheduleFastWriteLocked();
+                }
+            }
+        }
     }
 
     /**
@@ -4251,8 +4267,15 @@
         return uidState;
     }
 
-    private void createSandboxUidStateIfNotExistsForAppLocked(int uid) {
+    private void createSandboxUidStateIfNotExistsForAppLocked(int uid,
+            SparseBooleanArray knownUids) {
+        if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
+            return;
+        }
         final int sandboxUid = Process.toSdkSandboxUid(uid);
+        if (knownUids != null) {
+            knownUids.put(sandboxUid, true);
+        }
         getUidStateLocked(sandboxUid, true);
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
index 23a384f..bc6ef20 100644
--- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.appop;
 
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -30,6 +31,7 @@
 import static android.app.AppOpsManager.OP_NONE;
 import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS;
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
 import static android.app.AppOpsManager.UID_STATE_TOP;
@@ -139,7 +141,6 @@
     }
 
     private int evalModeInternal(int uid, int code, int uidState, int uidCapability) {
-
         if (getUidAppWidgetVisible(uid) || mActivityManagerInternal.isPendingTopUid(uid)
                 || mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid)) {
             return MODE_ALLOWED;
@@ -173,6 +174,8 @@
             case OP_RECORD_AUDIO:
             case OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO:
                 return PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+            case OP_TAKE_AUDIO_FOCUS:
+                return PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
             default:
                 return PROCESS_CAPABILITY_NONE;
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c59f4f7..559a1d6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -34,6 +34,7 @@
 import static android.media.audio.Flags.automaticBtDeviceType;
 import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
 import static android.media.audio.Flags.focusFreezeTestApi;
+import static android.media.audio.Flags.foregroundAudioControl;
 import static android.media.audiopolicy.Flags.enableFadeManagerConfiguration;
 import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.os.Process.INVALID_UID;
@@ -1356,7 +1357,8 @@
 
         mMusicFxHelper = new MusicFxHelper(mContext, mAudioHandler);
 
-        mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive());
+        mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive(), mAppOps,
+                context.getPackageManager());
     }
 
     private void initVolumeStreamStates() {
@@ -4517,7 +4519,8 @@
     }
 
     private void dumpFlags(PrintWriter pw) {
-        pw.println("\nFun with Flags: ");
+
+        pw.println("\nFun with Flags:");
         pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:"
                 + autoPublicVolumeApiHardening());
         pw.println("\tandroid.media.audio.Flags.automaticBtDeviceType:"
@@ -4528,8 +4531,8 @@
                 + focusFreezeTestApi());
         pw.println("\tcom.android.media.audio.disablePrescaleAbsoluteVolume:"
                 + disablePrescaleAbsoluteVolume());
-        pw.println("\tandroid.media.audiopolicy.enableFadeManagerConfiguration:"
-                + enableFadeManagerConfiguration());
+        pw.println("\tandroid.media.audio.foregroundAudioControl:"
+                + foregroundAudioControl());
     }
 
     private void dumpAudioMode(PrintWriter pw) {
@@ -10175,10 +10178,38 @@
                     .record();
             return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
         }
+
+        // does caller have system privileges to bypass HardeningEnforcer
+        boolean permissionOverridesCheck = false;
+        if ((mContext.checkCallingOrSelfPermission(
+                Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+                == PackageManager.PERMISSION_GRANTED)
+                || (mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_AUDIO_ROUTING)
+                == PackageManager.PERMISSION_GRANTED)) {
+            permissionOverridesCheck = true;
+        } else if (uid < UserHandle.AID_APP_START) {
+            permissionOverridesCheck = true;
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (!permissionOverridesCheck && mHardeningEnforcer.blockFocusMethod(uid,
+                    HardeningEnforcer.METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS,
+                    clientId, durationHint, callingPackageName)) {
+                final String reason = "Audio focus request blocked by hardening";
+                Log.w(TAG, reason);
+                mmi.set(MediaMetrics.Property.EARLY_RETURN, reason).record();
+                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+
         mmi.record();
         return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
                 clientId, callingPackageName, attributionTag, flags, sdk,
-                forceFocusDuckingForAccessibility(aa, durationHint, uid), -1 /*testUid, ignored*/);
+                forceFocusDuckingForAccessibility(aa, durationHint, uid), -1 /*testUid, ignored*/,
+                permissionOverridesCheck);
     }
 
     /** see {@link AudioManager#requestAudioFocusForTest(AudioFocusRequest, String, int, int)} */
@@ -10195,7 +10226,7 @@
         }
         return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
                 clientId, callingPackageName, null, flags,
-                sdk, false /*forceDuck*/, fakeUid);
+                sdk, false /*forceDuck*/, fakeUid, true /*permissionOverridesCheck*/);
     }
 
     public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
@@ -11639,6 +11670,7 @@
             pw.println("\nMessage handler is null");
         }
         dumpFlags(pw);
+        mHardeningEnforcer.dump(pw);
         mMediaFocusControl.dump(pw);
         dumpStreamStates(pw);
         dumpVolumeGroups(pw);
diff --git a/services/core/java/com/android/server/audio/HardeningEnforcer.java b/services/core/java/com/android/server/audio/HardeningEnforcer.java
index 4ceb83b2..409ed17 100644
--- a/services/core/java/com/android/server/audio/HardeningEnforcer.java
+++ b/services/core/java/com/android/server/audio/HardeningEnforcer.java
@@ -18,13 +18,21 @@
 import static android.media.audio.Flags.autoPublicVolumeApiHardening;
 
 import android.Manifest;
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.media.AudioFocusRequest;
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.UserHandle;
 import android.text.TextUtils;
-import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.utils.EventLogger;
+
+import java.io.PrintWriter;
 
 /**
  * Class to encapsulate all audio API hardening operations
@@ -32,10 +40,19 @@
 public class HardeningEnforcer {
 
     private static final String TAG = "AS.HardeningEnforcer";
+    private static final boolean DEBUG = false;
+    private static final int LOG_NB_EVENTS = 20;
 
     final Context mContext;
+    final AppOpsManager mAppOps;
     final boolean mIsAutomotive;
 
+    final ActivityManager mActivityManager;
+    final PackageManager mPackageManager;
+
+    final EventLogger mEventLogger = new EventLogger(LOG_NB_EVENTS,
+            "Hardening enforcement");
+
     /**
      * Matches calls from {@link AudioManager#setStreamVolume(int, int, int)}
      */
@@ -56,10 +73,24 @@
      * Matches calls from {@link AudioManager#setRingerMode(int)}
      */
     public static final int METHOD_AUDIO_MANAGER_SET_RINGER_MODE = 200;
+    /**
+     * Matches calls from {@link AudioManager#requestAudioFocus(AudioFocusRequest)}
+     * and legacy variants
+     */
+    public static final int METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS = 300;
 
-    public HardeningEnforcer(Context ctxt, boolean isAutomotive) {
+    public HardeningEnforcer(Context ctxt, boolean isAutomotive, AppOpsManager appOps,
+            PackageManager pm) {
         mContext = ctxt;
         mIsAutomotive = isAutomotive;
+        mAppOps = appOps;
+        mActivityManager = ctxt.getSystemService(ActivityManager.class);
+        mPackageManager = pm;
+    }
+
+    protected void dump(PrintWriter pw) {
+        // log
+        mEventLogger.dump(pw);
     }
 
     /**
@@ -84,7 +115,7 @@
             }
             // TODO metrics?
             // TODO log for audio dumpsys?
-            Log.e(TAG, "Preventing volume method " + volumeMethod + " for "
+            Slog.e(TAG, "Preventing volume method " + volumeMethod + " for "
                     + getPackNameForUid(Binder.getCallingUid()));
             return true;
         }
@@ -92,10 +123,40 @@
         return false;
     }
 
+    /**
+     * Checks whether the call in the current thread should be allowed or blocked
+     * @param focusMethod name of the method to check, for logging purposes
+     * @param clientId id of the requester
+     * @param durationHint focus type being requested
+     * @return false if the method call is allowed, true if it should be a no-op
+     */
+    protected boolean blockFocusMethod(int callingUid, int focusMethod, @NonNull String clientId,
+            int durationHint, @NonNull String packageName) {
+        if (packageName.isEmpty()) {
+            packageName = getPackNameForUid(callingUid);
+        }
+
+        if (checkAppOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, callingUid, packageName)) {
+            if (DEBUG) {
+                Slog.i(TAG, "blockFocusMethod pack:" + packageName + " NOT blocking");
+            }
+            return false;
+        }
+
+        String errorMssg = "Focus request DENIED for uid:" + callingUid
+                + " clientId:" + clientId + " req:" + durationHint
+                + " procState:" + mActivityManager.getUidProcessState(callingUid);
+
+        // TODO metrics
+        mEventLogger.enqueueAndSlog(errorMssg, EventLogger.Event.ALOGI, TAG);
+
+        return true;
+    }
+
     private String getPackNameForUid(int uid) {
         final long token = Binder.clearCallingIdentity();
         try {
-            final String[] names = mContext.getPackageManager().getPackagesForUid(uid);
+            final String[] names = mPackageManager.getPackagesForUid(uid);
             if (names == null
                     || names.length == 0
                     || TextUtils.isEmpty(names[0])) {
@@ -106,4 +167,18 @@
             Binder.restoreCallingIdentity(token);
         }
     }
+
+    /**
+     * Checks the given op without throwing
+     * @param op the appOp code
+     * @param uid the calling uid
+     * @param packageName the package name of the caller
+     * @return return false if the operation is not allowed
+     */
+    private boolean checkAppOp(int op, int uid, @NonNull String packageName) {
+        if (mAppOps.checkOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 1376bde..35d38e2 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -1090,11 +1090,14 @@
      *                  accessibility.
      * @param testUid ignored if flags doesn't contain AudioManager.AUDIOFOCUS_FLAG_TEST
      *                otherwise the UID being injected for testing
+     * @param permissionOverridesCheck true if permission checks guaranteed that the call should
+     *                                 go through, false otherwise (e.g. non-privileged caller)
      * @return
      */
     protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
             IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
-            String attributionTag, int flags, int sdk, boolean forceDuck, int testUid) {
+            String attributionTag, int flags, int sdk, boolean forceDuck, int testUid,
+            boolean permissionOverridesCheck) {
         new MediaMetrics.Item(mMetricsId)
                 .setUid(Binder.getCallingUid())
                 .set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
@@ -1126,10 +1129,9 @@
             return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
         }
 
-        if ((flags != AudioManager.AUDIOFOCUS_FLAG_TEST)
-                // note we're using the real uid for appOp evaluation
-                && (mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
-                        callingPackageName, attributionTag, null) != AppOpsManager.MODE_ALLOWED)) {
+        final int res = mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
+                callingPackageName, attributionTag, null);
+        if (!permissionOverridesCheck && res != AppOpsManager.MODE_ALLOWED) {
             return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
         }
 
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index cd064ae..38051c1 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -21,8 +21,8 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 
 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
@@ -1065,7 +1065,8 @@
     }
 
     private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
-        @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int mCurrentBaseState;
+        @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
+        int mCurrentBaseState;
 
         @Override
         public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates,
@@ -1078,8 +1079,10 @@
 
         @Override
         public void onStateChanged(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier) {
-            if (identifier < MINIMUM_DEVICE_STATE || identifier > MAXIMUM_DEVICE_STATE) {
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier) {
+            if (identifier < MINIMUM_DEVICE_STATE_IDENTIFIER
+                    || identifier > MAXIMUM_DEVICE_STATE_IDENTIFIER) {
                 throw new IllegalArgumentException("Invalid identifier: " + identifier);
             }
 
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
index 65b393a..b865c1d9 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
@@ -16,8 +16,8 @@
 
 package com.android.server.devicestate;
 
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 
 import android.annotation.IntDef;
 import android.annotation.IntRange;
@@ -133,10 +133,12 @@
          *
          * @param identifier the identifier of the new device state.
          *
-         * @throws IllegalArgumentException if the state is less than {@link MINIMUM_DEVICE_STATE}
-         * or greater than {@link MAXIMUM_DEVICE_STATE}.
+         * @throws IllegalArgumentException if the state is less than
+         * {@link MINIMUM_DEVICE_STATE_IDENTIFIER} or greater than
+         * {@link MAXIMUM_DEVICE_STATE_IDENTIFIER}.
          */
         void onStateChanged(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier);
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier);
     }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 4bb8e19..bc169ca 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2901,16 +2901,12 @@
     @GuardedBy("ImfLock.class")
     void clearClientSessionsLocked() {
         if (getCurMethodLocked() != null) {
-            // TODO(b/322816970): Replace this with lambda.
-            mClientController.forAllClients(new Consumer<ClientState>() {
-
-                @GuardedBy("ImfLock.class")
-                @Override
-                public void accept(ClientState c) {
-                    clearClientSessionLocked(c);
-                    clearClientSessionForAccessibilityLocked(c);
-                }
-            });
+            // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
+            @SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession = c -> {
+                clearClientSessionLocked(c);
+                clearClientSessionForAccessibilityLocked(c);
+            };
+            mClientController.forAllClients(clearClientSession);
 
             finishSessionLocked(mEnabledSession);
             for (int i = 0; i < mEnabledAccessibilitySessions.size(); i++) {
@@ -4653,15 +4649,7 @@
         super.startImeTrace_enforcePermission();
         ImeTracing.getInstance().startTrace(null /* printwriter */);
         synchronized (ImfLock.class) {
-            // TODO(b/322816970): Replace this with lambda.
-            mClientController.forAllClients(new Consumer<ClientState>() {
-
-                @GuardedBy("ImfLock.class")
-                @Override
-                public void accept(ClientState c) {
-                    c.mClient.setImeTraceEnabled(true /* enabled */);
-                }
-            });
+            mClientController.forAllClients(c -> c.mClient.setImeTraceEnabled(true /* enabled */));
         }
     }
 
@@ -4673,15 +4661,7 @@
 
         ImeTracing.getInstance().stopTrace(null /* printwriter */);
         synchronized (ImfLock.class) {
-            // TODO(b/322816970): Replace this with lambda.
-            mClientController.forAllClients(new Consumer<ClientState>() {
-
-                @GuardedBy("ImfLock.class")
-                @Override
-                public void accept(ClientState c) {
-                    c.mClient.setImeTraceEnabled(false /* enabled */);
-                }
-            });
+            mClientController.forAllClients(c -> c.mClient.setImeTraceEnabled(false /* enabled */));
         }
     }
 
@@ -5916,15 +5896,12 @@
                 // We only have sessions when we bound to an input method. Remove this session
                 // from all clients.
                 if (getCurMethodLocked() != null) {
-                    // TODO(b/322816970): Replace this with lambda.
-                    mClientController.forAllClients(new Consumer<ClientState>() {
+                    // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
+                    @SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession =
+                            c -> clearClientSessionForAccessibilityLocked(c,
+                                    accessibilityConnectionId);
+                    mClientController.forAllClients(clearClientSession);
 
-                        @GuardedBy("ImfLock.class")
-                        @Override
-                        public void accept(ClientState c) {
-                            clearClientSessionForAccessibilityLocked(c, accessibilityConnectionId);
-                        }
-                    });
                     AccessibilitySessionState session = mEnabledAccessibilitySessions.get(
                             accessibilityConnectionId);
                     if (session != null) {
@@ -6126,24 +6103,21 @@
             }
             // Dump ClientController#mClients
             p.println("  ClientStates:");
-            // TODO(b/322816970): Replace this with lambda.
-            mClientController.forAllClients(new Consumer<ClientState>() {
+            // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
+            @SuppressWarnings("GuardedBy") Consumer<ClientState> clientControllerDump = c -> {
+                p.println("  " + c + ":");
+                p.println("    client=" + c.mClient);
+                p.println("    fallbackInputConnection="
+                        + c.mFallbackInputConnection);
+                p.println("    sessionRequested="
+                        + c.mSessionRequested);
+                p.println(
+                        "    sessionRequestedForAccessibility="
+                                + c.mSessionRequestedForAccessibility);
+                p.println("    curSession=" + c.mCurSession);
+            };
+            mClientController.forAllClients(clientControllerDump);
 
-                @GuardedBy("ImfLock.class")
-                @Override
-                public void accept(ClientState c) {
-                    p.println("  " + c + ":");
-                    p.println("    client=" + c.mClient);
-                    p.println("    fallbackInputConnection="
-                            + c.mFallbackInputConnection);
-                    p.println("    sessionRequested="
-                            + c.mSessionRequested);
-                    p.println(
-                            "    sessionRequestedForAccessibility="
-                                    + c.mSessionRequestedForAccessibility);
-                    p.println("    curSession=" + c.mCurSession);
-                }
-            });
             p.println("  mCurMethodId=" + getSelectedMethodIdLocked());
             client = mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq=" + getSequenceNumberLocked());
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 1546895..bbb19e3 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -550,8 +550,8 @@
                     break;
                 case RECORD_CONTENT_TASK:
                     IBinder taskWindowContainerToken =
-                            mProjectionGrant.getLaunchCookieInternal() == null ? null
-                                    : mProjectionGrant.getLaunchCookieInternal().binder;
+                            mProjectionGrant.getLaunchCookie() == null ? null
+                                    : mProjectionGrant.getLaunchCookie().binder;
                     setReviewedConsentSessionLocked(
                             ContentRecordingSession.createTaskSession(taskWindowContainerToken));
                     break;
@@ -603,17 +603,6 @@
         return projection;
     }
 
-    /**
-     * Test API mirroring the types in the aidl interface for access outside the projection
-     * package.
-     */
-    @VisibleForTesting
-    public IMediaProjection createProjectionInternal(int processUid, String packageName, int type,
-            boolean isPermanentGrant) {
-        return createProjectionInternal(processUid, packageName, type, isPermanentGrant,
-                Binder.getCallingUserHandle());
-    }
-
     // TODO(b/261563516): Remove internal method and test aidl directly, here and elsewhere.
     @VisibleForTesting
     MediaProjection getProjectionInternal(int uid, String packageName) {
@@ -1203,10 +1192,6 @@
         @Override // Binder call
         public void setLaunchCookie(LaunchCookie launchCookie) {
             setLaunchCookie_enforcePermission();
-            setLaunchCookieInternal(launchCookie);
-        }
-
-        @VisibleForTesting void setLaunchCookieInternal(LaunchCookie launchCookie) {
             mLaunchCookie = launchCookie;
         }
 
@@ -1214,10 +1199,6 @@
         @Override // Binder call
         public LaunchCookie getLaunchCookie() {
             getLaunchCookie_enforcePermission();
-            return getLaunchCookieInternal();
-        }
-
-        @VisibleForTesting LaunchCookie getLaunchCookieInternal() {
             return mLaunchCookie;
         }
 
@@ -1225,11 +1206,6 @@
         @Override
         public boolean isValid() {
             isValid_enforcePermission();
-            return isValidInternal();
-        }
-
-        @VisibleForTesting
-        boolean isValidInternal() {
             synchronized (mLock) {
                 final long curMs = mClock.uptimeMillis();
                 final boolean hasTimedOut = curMs - mCreateTimeMs > mTimeoutMs;
@@ -1260,11 +1236,6 @@
         @Override
         public void notifyVirtualDisplayCreated(int displayId) {
             notifyVirtualDisplayCreated_enforcePermission();
-            notifyVirtualDisplayCreatedInternal(displayId);
-        }
-
-        @VisibleForTesting
-        void notifyVirtualDisplayCreatedInternal(int displayId) {
             synchronized (mLock) {
                 mVirtualDisplayId = displayId;
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index d987622..8729522 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -1143,10 +1143,9 @@
     };
 
     private static final class PackageManagerHelperImpl implements PackageManagerHelper {
-        private static final class PackageStateUsers {
+        private static class PackageStateUsers {
             private PackageState mPackageState;
-            private Boolean mDefinesOverlayable = null;
-            private final ArraySet<Integer> mInstalledUsers = new ArraySet<>();
+            private final Set<Integer> mInstalledUsers = new ArraySet<>();
             private PackageStateUsers(@NonNull PackageState packageState) {
                 this.mPackageState = packageState;
             }
@@ -1196,11 +1195,13 @@
             return userPackages;
         }
 
-        private PackageStateUsers getRawPackageStateForUser(@NonNull final String packageName,
+        @Override
+        @Nullable
+        public PackageState getPackageStateForUser(@NonNull final String packageName,
                 final int userId) {
             final PackageStateUsers pkg = mCache.get(packageName);
             if (pkg != null && pkg.mInstalledUsers.contains(userId)) {
-                return pkg;
+                return pkg.mPackageState;
             }
             try {
                 if (!mPackageManager.isPackageAvailable(packageName, userId)) {
@@ -1214,14 +1215,8 @@
             return addPackageUser(packageName, userId);
         }
 
-        @Override
-        public PackageState getPackageStateForUser(@NonNull final String packageName,
-                final int userId) {
-            final PackageStateUsers pkg = getRawPackageStateForUser(packageName, userId);
-            return pkg != null ? pkg.mPackageState : null;
-        }
-
-        private PackageStateUsers addPackageUser(@NonNull final String packageName,
+        @NonNull
+        private PackageState addPackageUser(@NonNull final String packageName,
                 final int user) {
             final PackageState pkg = mPackageManagerInternal.getPackageStateInternal(packageName);
             if (pkg == null) {
@@ -1233,20 +1228,20 @@
         }
 
         @NonNull
-        private PackageStateUsers addPackageUser(@NonNull final PackageState pkg,
+        private PackageState addPackageUser(@NonNull final PackageState pkg,
                 final int user) {
             PackageStateUsers pkgUsers = mCache.get(pkg.getPackageName());
             if (pkgUsers == null) {
                 pkgUsers = new PackageStateUsers(pkg);
                 mCache.put(pkg.getPackageName(), pkgUsers);
-            } else if (pkgUsers.mPackageState != pkg) {
+            } else {
                 pkgUsers.mPackageState = pkg;
-                pkgUsers.mDefinesOverlayable = null;
             }
             pkgUsers.mInstalledUsers.add(user);
-            return pkgUsers;
+            return pkgUsers.mPackageState;
         }
 
+
         @NonNull
         private void removePackageUser(@NonNull final String packageName, final int user) {
             final PackageStateUsers pkgUsers = mCache.get(packageName);
@@ -1264,15 +1259,15 @@
             }
         }
 
+        @Nullable
         public PackageState onPackageAdded(@NonNull final String packageName, final int userId) {
-            final var pu = addPackageUser(packageName, userId);
-            return pu != null ? pu.mPackageState : null;
+            return addPackageUser(packageName, userId);
         }
 
+        @Nullable
         public PackageState onPackageUpdated(@NonNull final String packageName,
                 final int userId) {
-            final var pu = addPackageUser(packageName, userId);
-            return pu != null ? pu.mPackageState : null;
+            return addPackageUser(packageName, userId);
         }
 
         public void onPackageRemoved(@NonNull final String packageName, final int userId) {
@@ -1312,30 +1307,22 @@
             return (pkgs.length == 0) ? null : pkgs[0];
         }
 
+        @Nullable
         @Override
         public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
                 @NonNull String targetOverlayableName, int userId)
                 throws IOException {
-            final var psu = getRawPackageStateForUser(packageName, userId);
-            final var pkg = (psu == null || psu.mPackageState == null)
-                    ? null : psu.mPackageState.getAndroidPackage();
+            var packageState = getPackageStateForUser(packageName, userId);
+            var pkg = packageState == null ? null : packageState.getAndroidPackage();
             if (pkg == null) {
                 throw new IOException("Unable to get target package");
             }
 
-            if (Boolean.FALSE.equals(psu.mDefinesOverlayable)) {
-                return null;
-            }
-
             ApkAssets apkAssets = null;
             try {
                 apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(),
                         ApkAssets.PROPERTY_ONLY_OVERLAYABLES);
-                if (psu.mDefinesOverlayable == null) {
-                    psu.mDefinesOverlayable = apkAssets.definesOverlayable();
-                }
-                return Boolean.FALSE.equals(psu.mDefinesOverlayable)
-                        ? null : apkAssets.getOverlayableInfo(targetOverlayableName);
+                return apkAssets.getOverlayableInfo(targetOverlayableName);
             } finally {
                 if (apkAssets != null) {
                     try {
@@ -1349,29 +1336,24 @@
         @Override
         public boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
                 throws IOException {
-            final var psu = getRawPackageStateForUser(targetPackageName, userId);
-            var pkg = (psu == null || psu.mPackageState == null)
-                    ? null : psu.mPackageState.getAndroidPackage();
+            var packageState = getPackageStateForUser(targetPackageName, userId);
+            var pkg = packageState == null ? null : packageState.getAndroidPackage();
             if (pkg == null) {
                 throw new IOException("Unable to get target package");
             }
 
-            if (psu.mDefinesOverlayable == null) {
-                ApkAssets apkAssets = null;
-                try {
-                    apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(),
-                            ApkAssets.PROPERTY_ONLY_OVERLAYABLES);
-                    psu.mDefinesOverlayable = apkAssets.definesOverlayable();
-                } finally {
-                    if (apkAssets != null) {
-                        try {
-                            apkAssets.close();
-                        } catch (Throwable ignored) {
-                        }
+            ApkAssets apkAssets = null;
+            try {
+                apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath());
+                return apkAssets.definesOverlayable();
+            } finally {
+                if (apkAssets != null) {
+                    try {
+                        apkAssets.close();
+                    } catch (Throwable ignored) {
                     }
                 }
             }
-            return psu.mDefinesOverlayable;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/ondeviceintelligence/OWNERS b/services/core/java/com/android/server/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..09774f7
--- /dev/null
+++ b/services/core/java/com/android/server/ondeviceintelligence/OWNERS
@@ -0,0 +1 @@
+file:/core/java/android/app/ondeviceintelligence/OWNERS
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 85d2df3..bbce26c 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -27,11 +27,14 @@
 import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
 import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.Flags;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -50,9 +53,15 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Set;
 
 final class PackageAbiHelperImpl implements PackageAbiHelper {
 
+    @Nullable
+    private static String[] sNativelySupported32BitAbis = null;
+    @Nullable
+    private static String[] sNativelySupported64BitAbis = null;
+
     private static String calculateBundledApkRoot(final String codePathString) {
         final File codePath = new File(codePathString);
         final File codeRoot;
@@ -122,13 +131,20 @@
         }
     }
 
-    private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws
-            PackageManagerException {
+    private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet,
+            boolean forceMatch) throws PackageManagerException {
         if (copyRet < 0) {
             if (copyRet != PackageManager.NO_NATIVE_LIBRARIES
                     && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
                 throw new PackageManagerException(copyRet, message);
             }
+
+            if (forceMatch && copyRet == PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+                throw new PackageManagerException(
+                        PackageManager.INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS,
+                        "The multiArch app's native libs don't support all the natively"
+                                + " supported ABIs of the device.");
+            }
         }
     }
 
@@ -296,7 +312,40 @@
         return new Abis(primaryCpuAbi, secondaryCpuAbi);
     }
 
+    @NonNull
+    private static String[] getNativelySupportedAbis(@NonNull String[] supportedAbis) {
+        Set<String> nativelySupportedAbis = new ArraySet<>();
+        for (int i = 0; i < supportedAbis.length; i++) {
+            final String currentAbi = supportedAbis[i];
+            // In presence of a native bridge this means the Abi is emulated.
+            final String currentIsa = VMRuntime.getInstructionSet(currentAbi);
+            if (TextUtils.isEmpty(SystemProperties.get("ro.dalvik.vm.isa." + currentIsa))) {
+                nativelySupportedAbis.add(currentAbi);
+            }
+        }
+        return nativelySupportedAbis.toArray(new String[0]);
+    }
+
+    private static String[] getNativelySupported32BitAbis() {
+        if (sNativelySupported32BitAbis != null) {
+            return sNativelySupported32BitAbis;
+        }
+
+        sNativelySupported32BitAbis = getNativelySupportedAbis(Build.SUPPORTED_32_BIT_ABIS);
+        return sNativelySupported32BitAbis;
+    }
+
+    private static String[] getNativelySupported64BitAbis() {
+        if (sNativelySupported64BitAbis != null) {
+            return sNativelySupported64BitAbis;
+        }
+
+        sNativelySupported64BitAbis = getNativelySupportedAbis(Build.SUPPORTED_64_BIT_ABIS);
+        return sNativelySupported64BitAbis;
+    }
+
     @Override
+    @SuppressWarnings("AndroidFrameworkCompatChange") // the check is before the apk is installed
     public Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isSystemApp,
             boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir)
             throws PackageManagerException {
@@ -334,18 +383,33 @@
             primaryCpuAbi = null;
             secondaryCpuAbi = null;
             if (pkg.isMultiArch()) {
+                // Force the match for these cases
+                // 1. pkg.getTargetSdkVersion >= Build.VERSION_CODES.VANILLA_ICE_CREAM
+                // 2. cpuAbiOverride is null. If it is non-null, it is set via shell for testing
+                final boolean forceMatch = Flags.forceMultiArchNativeLibsMatch()
+                        && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.VANILLA_ICE_CREAM
+                        && cpuAbiOverride == null;
+
+                String[] supported32BitAbis = forceMatch ? getNativelySupported32BitAbis()
+                        : Build.SUPPORTED_32_BIT_ABIS;
+                String[] supported64BitAbis = forceMatch ? getNativelySupported64BitAbis()
+                        : Build.SUPPORTED_64_BIT_ABIS;
+
+                final boolean systemSupports32BitAbi = supported32BitAbis.length > 0;
+                final boolean systemSupports64BitAbi = supported64BitAbis.length > 0;
+
                 int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
                 int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
-                if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+                if (systemSupports32BitAbi) {
                     if (extractLibs) {
                         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
                         abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
-                                nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
+                                nativeLibraryRoot, supported32BitAbis,
                                 useIsaSpecificSubdirs, onIncremental);
                     } else {
                         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
                         abi32 = NativeLibraryHelper.findSupportedAbi(
-                                handle, Build.SUPPORTED_32_BIT_ABIS);
+                                handle, supported32BitAbis);
                     }
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
@@ -357,24 +421,26 @@
                 }
 
                 maybeThrowExceptionForMultiArchCopy(
-                        "Error unpackaging 32 bit native libs for multiarch app.", abi32);
+                        "Error unpackaging 32 bit native libs for multiarch app.", abi32,
+                        forceMatch && systemSupports32BitAbi);
 
-                if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+                if (systemSupports64BitAbi) {
                     if (extractLibs) {
                         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
                         abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
-                                nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
+                                nativeLibraryRoot, supported64BitAbis,
                                 useIsaSpecificSubdirs, onIncremental);
                     } else {
                         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
                         abi64 = NativeLibraryHelper.findSupportedAbi(
-                                handle, Build.SUPPORTED_64_BIT_ABIS);
+                                handle, supported64BitAbis);
                     }
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
 
                 maybeThrowExceptionForMultiArchCopy(
-                        "Error unpackaging 64 bit native libs for multiarch app.", abi64);
+                        "Error unpackaging 64 bit native libs for multiarch app.", abi64,
+                        forceMatch && systemSupports64BitAbi);
 
                 if (abi64 >= 0) {
                     // Shared library native libs should be in the APK zip aligned
@@ -382,11 +448,11 @@
                         throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                                 "Shared library native lib extraction not supported");
                     }
-                    primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
+                    primaryCpuAbi = supported64BitAbis[abi64];
                 }
 
                 if (abi32 >= 0) {
-                    final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
+                    final String abi = supported32BitAbis[abi32];
                     if (abi64 >= 0) {
                         if (pkg.is32BitAbiPreferred()) {
                             secondaryCpuAbi = primaryCpuAbi;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index f44fcf0..21e2bf2 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -42,6 +42,7 @@
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.AttributionFlags;
 import android.app.IActivityManager;
+import android.companion.virtual.VirtualDeviceManager;
 import android.content.AttributionSource;
 import android.content.AttributionSourceState;
 import android.content.Context;
@@ -78,6 +79,7 @@
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.TriFunction;
 import com.android.server.LocalServices;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
 import com.android.server.pm.pkg.AndroidPackage;
@@ -135,6 +137,9 @@
     @Nullable
     private HotwordDetectionServiceProvider mHotwordDetectionServiceProvider;
 
+    @Nullable
+    private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
+
     PermissionManagerService(@NonNull Context context,
             @NonNull ArrayMap<String, FeatureInfo> availableFeatures) {
         // The package info cache is the cache for package and permission information.
@@ -146,6 +151,8 @@
         mContext = context;
         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
+        mVirtualDeviceManagerInternal =
+                LocalServices.getService(VirtualDeviceManagerInternal.class);
 
         mAttributionSourceRegistry = new AttributionSourceRegistry(context);
 
@@ -246,16 +253,30 @@
             return PackageManager.PERMISSION_DENIED;
         }
 
+        String persistentDeviceId = getPersistentDeviceId(deviceId);
+
         final CheckPermissionDelegate checkPermissionDelegate;
         synchronized (mLock) {
             checkPermissionDelegate = mCheckPermissionDelegate;
         }
-
-        if (checkPermissionDelegate == null)  {
-            return mPermissionManagerServiceImpl.checkUidPermission(uid, permissionName, deviceId);
+        if (checkPermissionDelegate == null) {
+            return mPermissionManagerServiceImpl.checkUidPermission(uid, permissionName,
+                    persistentDeviceId);
         }
         return checkPermissionDelegate.checkUidPermission(uid, permissionName,
-                deviceId, mPermissionManagerServiceImpl::checkUidPermission);
+                persistentDeviceId, mPermissionManagerServiceImpl::checkUidPermission);
+    }
+
+    private String getPersistentDeviceId(int deviceId) {
+        if (deviceId == Context.DEVICE_ID_DEFAULT) {
+            return VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
+        }
+
+        if (mVirtualDeviceManagerInternal == null) {
+            mVirtualDeviceManagerInternal =
+                    LocalServices.getService(VirtualDeviceManagerInternal.class);
+        }
+        return mVirtualDeviceManagerInternal.getPersistentIdForDevice(deviceId);
     }
 
     @Override
@@ -608,15 +629,17 @@
     @Override
     public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
             int deviceId, int userId) {
+        String persistentDeviceId = getPersistentDeviceId(deviceId);
         return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
-                permissionName, deviceId, userId);
+                permissionName, persistentDeviceId, userId);
     }
 
     @Override
     public boolean isPermissionRevokedByPolicy(String packageName, String permissionName,
             int deviceId, int userId) {
+        String persistentDeviceId = getPersistentDeviceId(deviceId);
         return mPermissionManagerServiceImpl.isPermissionRevokedByPolicy(packageName,
-                permissionName, deviceId, userId);
+                permissionName, persistentDeviceId, userId);
     }
 
     @Override
@@ -914,13 +937,13 @@
          *
          * @param uid the UID to be checked
          * @param permissionName the name of the permission to be checked
-         * @param deviceId The device ID
+         * @param persistentDeviceId The persistent device ID
          * @param superImpl the original implementation that can be delegated to
          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
          * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
          */
-        int checkUidPermission(int uid, @NonNull String permissionName, int deviceId,
-                TriFunction<Integer, String, Integer, Integer> superImpl);
+        int checkUidPermission(int uid, @NonNull String permissionName, String persistentDeviceId,
+                TriFunction<Integer, String, String, Integer> superImpl);
 
         /**
          * @return list of delegated permissions
@@ -965,17 +988,18 @@
         }
 
         @Override
-        public int checkUidPermission(int uid, @NonNull String permissionName, int deviceId,
-                @NonNull TriFunction<Integer, String, Integer, Integer> superImpl) {
+        public int checkUidPermission(int uid, @NonNull String permissionName,
+                String persistentDeviceId,
+                @NonNull TriFunction<Integer, String, String, Integer> superImpl) {
             if (uid == mDelegatedUid && isDelegatedPermission(permissionName)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    return superImpl.apply(Process.SHELL_UID, permissionName, deviceId);
+                    return superImpl.apply(Process.SHELL_UID, permissionName, persistentDeviceId);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
             }
-            return superImpl.apply(uid, permissionName, deviceId);
+            return superImpl.apply(uid, permissionName, persistentDeviceId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index c5b637d..70913c3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -682,7 +682,7 @@
     }
 
     @Override
-    public int getPermissionFlags(String packageName, String permName, String persistentDeviceId,
+    public int getPermissionFlags(String packageName, String permName, String deviceId,
             int userId) {
         final int callingUid = Binder.getCallingUid();
         return getPermissionFlagsInternal(packageName, permName, callingUid, userId);
@@ -726,8 +726,7 @@
 
     @Override
     public void updatePermissionFlags(String packageName, String permName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, String persistentDeviceId,
-            int userId) {
+            int flagValues, boolean checkAdjustPolicyFlagPermission, String deviceId, int userId) {
         final int callingUid = Binder.getCallingUid();
         boolean overridePolicy = false;
 
@@ -917,8 +916,7 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
-            int userId) {
+    public int checkPermission(String pkgName, String permName, String deviceId, int userId) {
         if (!mUserManagerInt.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
         }
@@ -985,11 +983,11 @@
     }
 
     private int checkUidPermission(int uid, String permName) {
-        return checkUidPermission(uid, permName, Context.DEVICE_ID_DEFAULT);
+        return checkUidPermission(uid, permName, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
     }
 
     @Override
-    public int checkUidPermission(int uid, String permName, int deviceId) {
+    public int checkUidPermission(int uid, String permName, String deviceId) {
         final int userId = UserHandle.getUserId(uid);
         if (!mUserManagerInt.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
@@ -1001,7 +999,7 @@
 
     @Override
     public Map<String, PermissionManager.PermissionState> getAllPermissionStates(
-            @NonNull String packageName, @NonNull String persistentDeviceId, int userId) {
+            @NonNull String packageName, @NonNull String deviceId, int userId) {
         throw new UnsupportedOperationException(
                 "This method is supported in newer implementation only");
     }
@@ -1315,8 +1313,8 @@
     }
 
     @Override
-    public void grantRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId) {
+    public void grantRuntimePermission(String packageName, String permName, String deviceId,
+            int userId) {
         final int callingUid = Binder.getCallingUid();
         final boolean overridePolicy =
                 checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY)
@@ -1489,12 +1487,13 @@
     }
 
     @Override
-    public void revokeRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId, String reason) {
+    public void revokeRuntimePermission(String packageName, String permName, String deviceId,
+            int userId, String reason) {
         final int callingUid = Binder.getCallingUid();
         final boolean overridePolicy =
                 checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY,
-                        Context.DEVICE_ID_DEFAULT) == PackageManager.PERMISSION_GRANTED;
+                        VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)
+                        == PackageManager.PERMISSION_GRANTED;
 
         revokeRuntimePermissionInternal(packageName, permName, overridePolicy, callingUid, userId,
                 reason, mDefaultPermissionCallback);
@@ -1880,7 +1879,7 @@
 
     @Override
     public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
-            int deviceId, @UserIdInt int userId) {
+            String deviceId, @UserIdInt int userId) {
         final int callingUid = Binder.getCallingUid();
         if (UserHandle.getCallingUserId() != userId) {
             mContext.enforceCallingPermission(
@@ -1943,7 +1942,7 @@
     }
 
     @Override
-    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int deviceId,
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, String deviceId,
             int userId) {
         if (UserHandle.getCallingUserId() != userId) {
             mContext.enforceCallingPermission(
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index 7c10425..47032ea 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -141,11 +141,11 @@
      *
      * @param packageName the package name for which to get the flags
      * @param permName the permission for which to get the flags
-     * @param persistentDeviceId The device for which to get the flags
+     * @param deviceId The device for which to get the flags
      * @param userId the user for which to get permission flags
      * @return the permission flags
      */
-    int getPermissionFlags(String packageName, String permName, String persistentDeviceId,
+    int getPermissionFlags(String packageName, String permName, String deviceId,
             @UserIdInt int userId);
 
     /**
@@ -156,11 +156,11 @@
      * @param permName The permission for which to update the flags
      * @param flagMask The flags which to replace
      * @param flagValues The flags with which to replace
-     * @param persistentDeviceId The device for which to update the permission flags
+     * @param deviceId The device for which to update the permission flags
      * @param userId The user for which to update the permission flags
      */
     void updatePermissionFlags(String packageName, String permName, int flagMask, int flagValues,
-            boolean checkAdjustPolicyFlagPermission, String persistentDeviceId,
+            boolean checkAdjustPolicyFlagPermission, String deviceId,
             @UserIdInt int userId);
 
     /**
@@ -295,12 +295,12 @@
      *
      * @param packageName the package to which to grant the permission
      * @param permName the permission name to grant
-     * @param persistentDeviceId the device for which to grant the permission
+     * @param deviceId the device for which to grant the permission
      * @param userId the user for which to grant the permission
      *
      * @see #revokeRuntimePermission(String, String, String, int, String)
      */
-    void grantRuntimePermission(String packageName, String permName, String persistentDeviceId,
+    void grantRuntimePermission(String packageName, String permName, String deviceId,
             @UserIdInt int userId);
 
     /**
@@ -316,13 +316,13 @@
      *
      * @param packageName the package from which to revoke the permission
      * @param permName the permission name to revoke
-     * @param persistentDeviceId the device for which to revoke the permission
+     * @param deviceId the device for which to revoke the permission
      * @param userId the user for which to revoke the permission
      * @param reason the reason for the revoke, or {@code null} for unspecified
      *
      * @see #grantRuntimePermission(String, String, String, int)
      */
-    void revokeRuntimePermission(String packageName, String permName, String persistentDeviceId,
+    void revokeRuntimePermission(String packageName, String permName, String deviceId,
             @UserIdInt int userId, String reason);
 
     /**
@@ -347,7 +347,7 @@
      * @return whether you can show permission rationale UI
      */
     boolean shouldShowRequestPermissionRationale(String packageName, String permName,
-            int deviceId, @UserIdInt int userId);
+            String deviceId, @UserIdInt int userId);
 
     /**
      * Checks whether a particular permission has been revoked for a package by policy. Typically,
@@ -361,8 +361,8 @@
      * @param userId the device for which you are checking the permission
      * @return whether the permission is restricted by policy
      */
-    boolean isPermissionRevokedByPolicy(String packageName, String permName, int deviceId,
-            @UserIdInt int userId);
+    boolean isPermissionRevokedByPolicy(String packageName, String permName,
+            String deviceId, @UserIdInt int userId);
 
     /**
      * Get set of permissions that have been split into more granular or dependent permissions.
@@ -389,11 +389,11 @@
      *
      * @param pkgName package name
      * @param permName permission name
-     * @param persistentDeviceId  persistent device ID
+     * @param deviceId  persistent device ID
      * @param userId user ID
      * @return permission result {@link PackageManager.PermissionResult}
      */
-    int checkPermission(String pkgName, String permName, String persistentDeviceId,
+    int checkPermission(String pkgName, String permName, String deviceId,
             @UserIdInt int userId);
 
     /**
@@ -401,23 +401,23 @@
      *
      * @param uid UID
      * @param permName permission name
-     * @param deviceId device ID
+     * @param deviceId persistent device ID
      * @return permission result {@link PackageManager.PermissionResult}
      */
-    int checkUidPermission(int uid, String permName, int deviceId);
+    int checkUidPermission(int uid, String permName, String deviceId);
 
     /**
      * Gets the permission states for requested package, persistent device and user.
      *
      * @param packageName name of the package you are checking against
-     * @param persistentDeviceId id of the persistent device you are checking against
+     * @param deviceId id of the persistent device you are checking against
      * @param userId id of the user for which to get permission flags
      * @return mapping of all permission states keyed by their permission names
      *
      * @hide
      */
     Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName,
-            @NonNull String persistentDeviceId, @UserIdInt int userId);
+            @NonNull String deviceId, @UserIdInt int userId);
 
     /**
      * Get all the package names requesting app op permissions.
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
index 91a778d..c18f856 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
@@ -121,24 +121,22 @@
     }
 
     @Override
-    public int getPermissionFlags(String packageName, String permName, String persistentDeviceId,
+    public int getPermissionFlags(String packageName, String permName, String deviceId,
             int userId) {
         Log.i(LOG_TAG, "getPermissionFlags(packageName = " + packageName + ", permName = "
-                + permName + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId
-                + ")");
-        return mService.getPermissionFlags(packageName, permName, persistentDeviceId, userId);
+                + permName + ", deviceId = " + deviceId + ", userId = " + userId + ")");
+        return mService.getPermissionFlags(packageName, permName, deviceId, userId);
     }
 
     @Override
     public void updatePermissionFlags(String packageName, String permName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, String persistentDeviceId,
-            int userId) {
+            int flagValues, boolean checkAdjustPolicyFlagPermission, String deviceId, int userId) {
         Log.i(LOG_TAG, "updatePermissionFlags(packageName = " + packageName + ", permName = "
                 + permName + ", flagMask = " + flagMask + ", flagValues = " + flagValues
                 + ", checkAdjustPolicyFlagPermission = " + checkAdjustPolicyFlagPermission
-                + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId + ")");
+                + ", deviceId = " + deviceId + ", userId = " + userId + ")");
         mService.updatePermissionFlags(packageName, permName, flagMask, flagValues,
-                checkAdjustPolicyFlagPermission, persistentDeviceId, userId);
+                checkAdjustPolicyFlagPermission, deviceId, userId);
     }
 
     @Override
@@ -186,21 +184,20 @@
     }
 
     @Override
-    public void grantRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId) {
+    public void grantRuntimePermission(String packageName, String permName, String deviceId,
+            int userId) {
         Log.i(LOG_TAG, "grantRuntimePermission(packageName = " + packageName + ", permName = "
-                + permName + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId
-                + ")");
-        mService.grantRuntimePermission(packageName, permName, persistentDeviceId, userId);
+                + permName + ", deviceId = " + deviceId + ", userId = " + userId + ")");
+        mService.grantRuntimePermission(packageName, permName, deviceId, userId);
     }
 
     @Override
-    public void revokeRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId, String reason) {
+    public void revokeRuntimePermission(String packageName, String permName, String deviceId,
+            int userId, String reason) {
         Log.i(LOG_TAG, "revokeRuntimePermission(packageName = " + packageName + ", permName = "
-                + permName + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId
-                + ", reason = " + reason + ")");
-        mService.revokeRuntimePermission(packageName, permName, persistentDeviceId, userId, reason);
+                + permName + ", deviceId = " + deviceId + ", userId = " + userId + ", reason = "
+                + reason + ")");
+        mService.revokeRuntimePermission(packageName, permName, deviceId, userId, reason);
     }
 
     @Override
@@ -212,16 +209,16 @@
 
     @Override
     public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
-            int deviceId, int userId) {
+            String deviceId, int userId) {
         Log.i(LOG_TAG, "shouldShowRequestPermissionRationale(packageName = " + packageName
-                + ", permName = " + permName + ", deviceId = " + deviceId
-                +  ", userId = " + userId + ")");
+                + ", permName = " + permName + ", deviceId = " + deviceId + ", userId = "
+                + userId + ")");
         return mService.shouldShowRequestPermissionRationale(packageName, permName, deviceId,
                 userId);
     }
 
     @Override
-    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int deviceId,
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, String deviceId,
             int userId) {
         Log.i(LOG_TAG, "isPermissionRevokedByPolicy(packageName = " + packageName + ", permName = "
                 + permName + ", deviceId = " + deviceId + ", userId = " + userId + ")");
@@ -235,26 +232,27 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
+    public int checkPermission(String pkgName, String permName, String deviceId,
             int userId) {
         Log.i(LOG_TAG, "checkPermission(pkgName = " + pkgName + ", permName = " + permName
-                + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId + ")");
-        return mService.checkPermission(pkgName, permName, persistentDeviceId, userId);
+                + ", deviceId = " + deviceId + ", userId = " + userId + ")");
+        return mService.checkPermission(pkgName, permName, deviceId, userId);
     }
 
     @Override
-    public int checkUidPermission(int uid, String permName, int deviceId) {
-        Log.i(LOG_TAG, "checkUidPermission(uid = " + uid + ", permName = "
-                + permName + ", deviceId = " + deviceId + ")");
+    public int checkUidPermission(int uid, String permName, String deviceId) {
+        Log.i(LOG_TAG, "checkUidPermission(uid = " + uid + ", permName = " + permName
+                + ", deviceId = " + deviceId + ")");
         return mService.checkUidPermission(uid, permName, deviceId);
     }
 
     @Override
     public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName,
-            @NonNull String persistentDeviceId, int userId) {
-        Log.i(LOG_TAG, "getAllPermissionStates(packageName = " + packageName
-                + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId + ")");
-        return mService.getAllPermissionStates(packageName, persistentDeviceId, userId);
+            @NonNull String deviceId, int userId) {
+        Log.i(LOG_TAG,
+                "getAllPermissionStates(packageName = " + packageName + ", deviceId = " + deviceId
+                        + ", userId = " + userId + ")");
+        return mService.getAllPermissionStates(packageName, deviceId, userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
index 0a4ff07..40139ba 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
@@ -154,12 +154,10 @@
     }
 
     @Override
-    public int getPermissionFlags(String packageName, String permName, String persistentDeviceId,
+    public int getPermissionFlags(String packageName, String permName, String deviceId,
             @UserIdInt int userId) {
-        int oldVal = mOldImplementation.getPermissionFlags(packageName, permName,
-                persistentDeviceId, userId);
-        int newVal = mNewImplementation.getPermissionFlags(packageName, permName,
-                persistentDeviceId, userId);
+        int oldVal = mOldImplementation.getPermissionFlags(packageName, permName, deviceId, userId);
+        int newVal = mNewImplementation.getPermissionFlags(packageName, permName, deviceId, userId);
 
         if (!Objects.equals(oldVal, newVal)) {
             signalImplDifference("getPermissionFlags");
@@ -169,12 +167,12 @@
 
     @Override
     public void updatePermissionFlags(String packageName, String permName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, String persistentDeviceId,
+            int flagValues, boolean checkAdjustPolicyFlagPermission, String deviceId,
             @UserIdInt int userId) {
         mOldImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
-                checkAdjustPolicyFlagPermission, persistentDeviceId, userId);
+                checkAdjustPolicyFlagPermission, deviceId, userId);
         mNewImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
-                checkAdjustPolicyFlagPermission, persistentDeviceId, userId);
+                checkAdjustPolicyFlagPermission, deviceId, userId);
     }
 
     @Override
@@ -239,21 +237,17 @@
     }
 
     @Override
-    public void grantRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, @UserIdInt int userId) {
-        mOldImplementation.grantRuntimePermission(packageName, permName, persistentDeviceId,
-                userId);
-        mNewImplementation.grantRuntimePermission(packageName, permName, persistentDeviceId,
-                userId);
+    public void grantRuntimePermission(String packageName, String permName, String deviceId,
+            @UserIdInt int userId) {
+        mOldImplementation.grantRuntimePermission(packageName, permName, deviceId, userId);
+        mNewImplementation.grantRuntimePermission(packageName, permName, deviceId, userId);
     }
 
     @Override
-    public void revokeRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, @UserIdInt int userId, String reason) {
-        mOldImplementation.revokeRuntimePermission(packageName, permName, persistentDeviceId,
-                userId, reason);
-        mNewImplementation.revokeRuntimePermission(packageName, permName, persistentDeviceId,
-                userId, reason);
+    public void revokeRuntimePermission(String packageName, String permName, String deviceId,
+            @UserIdInt int userId, String reason) {
+        mOldImplementation.revokeRuntimePermission(packageName, permName, deviceId, userId, reason);
+        mNewImplementation.revokeRuntimePermission(packageName, permName, deviceId, userId, reason);
     }
 
     @Override
@@ -265,7 +259,7 @@
 
     @Override
     public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
-            int deviceId, @UserIdInt int userId) {
+            String deviceId, @UserIdInt int userId) {
         boolean oldVal = mOldImplementation.shouldShowRequestPermissionRationale(packageName,
                 permName, deviceId,  userId);
         boolean newVal = mNewImplementation.shouldShowRequestPermissionRationale(packageName,
@@ -278,7 +272,7 @@
     }
 
     @Override
-    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int deviceId,
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, String deviceId,
             @UserIdInt int userId) {
         boolean oldVal = mOldImplementation.isPermissionRevokedByPolicy(packageName, permName,
                 deviceId, userId);
@@ -303,12 +297,9 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
-            int userId) {
-        int oldVal = mOldImplementation.checkPermission(pkgName, permName, persistentDeviceId,
-                userId);
-        int newVal = mNewImplementation.checkPermission(pkgName, permName, persistentDeviceId,
-                userId);
+    public int checkPermission(String pkgName, String permName, String deviceId, int userId) {
+        int oldVal = mOldImplementation.checkPermission(pkgName, permName, deviceId, userId);
+        int newVal = mNewImplementation.checkPermission(pkgName, permName, deviceId, userId);
 
         if (!Objects.equals(oldVal, newVal)) {
             signalImplDifference("checkPermission");
@@ -317,7 +308,7 @@
     }
 
     @Override
-    public int checkUidPermission(int uid, String permName, int deviceId) {
+    public int checkUidPermission(int uid, String permName, String deviceId) {
         int oldVal = mOldImplementation.checkUidPermission(uid, permName, deviceId);
         int newVal = mNewImplementation.checkUidPermission(uid, permName, deviceId);
 
@@ -329,8 +320,8 @@
 
     @Override
     public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName,
-            @NonNull String persistentDeviceId, int userId) {
-        return mNewImplementation.getAllPermissionStates(packageName, persistentDeviceId, userId);
+            @NonNull String deviceId, int userId) {
+        return mNewImplementation.getAllPermissionStates(packageName, deviceId, userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
index bc29e67..981d3d9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
@@ -159,11 +159,11 @@
     }
 
     @Override
-    public int getPermissionFlags(String packageName, String permName, String persistentDeviceId,
+    public int getPermissionFlags(String packageName, String permName, String deviceId,
             int userId) {
         Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl#getPermissionFlags");
         try {
-            return mService.getPermissionFlags(packageName, permName, persistentDeviceId, userId);
+            return mService.getPermissionFlags(packageName, permName, deviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
@@ -171,13 +171,12 @@
 
     @Override
     public void updatePermissionFlags(String packageName, String permName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, String persistentDeviceId,
-            int userId) {
+            int flagValues, boolean checkAdjustPolicyFlagPermission, String deviceId, int userId) {
         Trace.traceBegin(TRACE_TAG,
                 "TaggedTracingPermissionManagerServiceImpl#updatePermissionFlags");
         try {
             mService.updatePermissionFlags(packageName, permName, flagMask, flagValues,
-                    checkAdjustPolicyFlagPermission, persistentDeviceId, userId);
+                    checkAdjustPolicyFlagPermission, deviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
@@ -256,25 +255,24 @@
     }
 
     @Override
-    public void grantRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId) {
+    public void grantRuntimePermission(String packageName, String permName, String deviceId,
+            int userId) {
         Trace.traceBegin(TRACE_TAG,
                 "TaggedTracingPermissionManagerServiceImpl#grantRuntimePermission");
         try {
-            mService.grantRuntimePermission(packageName, permName, persistentDeviceId, userId);
+            mService.grantRuntimePermission(packageName, permName, deviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public void revokeRuntimePermission(String packageName, String permName,
-            String persistentDeviceId, int userId, String reason) {
+    public void revokeRuntimePermission(String packageName, String permName, String deviceId,
+            int userId, String reason) {
         Trace.traceBegin(TRACE_TAG,
                 "TaggedTracingPermissionManagerServiceImpl#revokeRuntimePermission");
         try {
-            mService.revokeRuntimePermission(packageName, permName, persistentDeviceId, userId,
-                    reason);
+            mService.revokeRuntimePermission(packageName, permName, deviceId, userId, reason);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
@@ -293,19 +291,19 @@
 
     @Override
     public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
-            int deviceId, int userId) {
+            String deviceId, int userId) {
         Trace.traceBegin(TRACE_TAG,
                 "TaggedTracingPermissionManagerServiceImpl#shouldShowRequestPermissionRationale");
         try {
-            return mService.shouldShowRequestPermissionRationale(
-                    packageName, permName, deviceId, userId);
+            return mService.shouldShowRequestPermissionRationale(packageName, permName, deviceId,
+                    userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int deviceId,
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, String deviceId,
             int userId) {
         Trace.traceBegin(TRACE_TAG,
                 "TaggedTracingPermissionManagerServiceImpl#isPermissionRevokedByPolicy");
@@ -328,18 +326,17 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
-            int userId) {
+    public int checkPermission(String pkgName, String permName, String deviceId, int userId) {
         Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl#checkPermission");
         try {
-            return mService.checkPermission(pkgName, permName, persistentDeviceId, userId);
+            return mService.checkPermission(pkgName, permName, deviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public int checkUidPermission(int uid, String permName, int deviceId) {
+    public int checkUidPermission(int uid, String permName, String deviceId) {
         Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl#checkUidPermission");
         try {
             return mService.checkUidPermission(uid, permName, deviceId);
@@ -350,11 +347,11 @@
 
     @Override
     public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName,
-            @NonNull String persistentDeviceId, int userId) {
+            @NonNull String deviceId, int userId) {
         Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl"
                 + "#getAllPermissionStates");
         try {
-            return mService.getAllPermissionStates(packageName, persistentDeviceId, userId);
+            return mService.getAllPermissionStates(packageName, deviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 76952b3..1b220a0 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -17,7 +17,7 @@
 package com.android.server.policy;
 
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -94,7 +94,7 @@
     private static final BooleanSupplier FALSE_BOOLEAN_SUPPLIER = () -> false;
 
     @VisibleForTesting
-    static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE,
+    static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER,
             "DEFAULT", 0 /* flags */);
 
     private static final String VENDOR_CONFIG_FILE_PATH = "etc/devicestate/";
diff --git a/services/core/java/com/android/server/utils/EventLogger.java b/services/core/java/com/android/server/utils/EventLogger.java
index 4772bbf..2e1049b 100644
--- a/services/core/java/com/android/server/utils/EventLogger.java
+++ b/services/core/java/com/android/server/utils/EventLogger.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Log;
+import android.util.Slog;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -84,6 +85,17 @@
         enqueue(event.printLog(logType, tag));
     }
 
+    /**
+     * Add a string-based event to the system log, and print it to the log with a specific severity.
+     * @param msg the message to appear in the log
+     * @param logType the log severity (verbose/info/warning/error)
+     * @param tag the tag under which the log entry will appear
+     */
+    public synchronized void enqueueAndSlog(String msg, @Event.LogType int logType, String tag) {
+        final Event event = new StringEvent(msg);
+        enqueue(event.printSlog(logType, tag));
+    }
+
     /** Dumps events into the given {@link DumpSink}. */
     public synchronized void dump(DumpSink dumpSink) {
         dumpSink.sink(mTag, new ArrayList<>(mEvents));
@@ -138,7 +150,7 @@
         /**
          * Causes the string message for the event to appear in the logcat.
          * Here is an example of how to create a new event (a StringEvent), adding it to the logger
-         * (an instance of AudioEventLogger) while also making it show in the logcat:
+         * (an instance of EventLogger) while also making it show in the logcat:
          * <pre>
          *     myLogger.log(
          *         (new StringEvent("something for logcat and logger")).printLog(MyClass.TAG) );
@@ -167,9 +179,9 @@
 
         /**
          * Same as {@link #printLog(String)} with a log type
-         * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}
-         * @param tag
-         * @return
+         * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}, {@link #ALOGW}
+         * @param tag the tag the log entry will be printed under
+         * @return the event itself
          */
         public Event printLog(@LogType int type, String tag) {
             switch (type) {
@@ -191,6 +203,32 @@
         }
 
         /**
+         * Causes the string message for the event to appear in the system log.
+         * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}, {@link #ALOGW}
+         * @param tag the tag the log entry will be printed under
+         * @return the event itself
+         * @see #printLog(int, String)
+         */
+        public Event printSlog(@LogType int type, String tag) {
+            switch (type) {
+                case ALOGI:
+                    Slog.i(tag, eventToString());
+                    break;
+                case ALOGE:
+                    Slog.e(tag, eventToString());
+                    break;
+                case ALOGW:
+                    Slog.w(tag, eventToString());
+                    break;
+                case ALOGV:
+                default:
+                    Slog.v(tag, eventToString());
+                    break;
+            }
+            return this;
+        }
+
+        /**
          * Convert event to String.
          * This method is only called when the logger history is about to the dumped,
          * so this method is where expensive String conversions should be made, not when the Event
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index db27f60..01d077a 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -22,12 +22,10 @@
 
 import android.annotation.NonNull;
 import android.app.compat.CompatChanges;
-import android.content.pm.PackageManager;
 import android.provider.DeviceConfig;
 
 import com.android.internal.annotations.GuardedBy;
 
-import java.util.HashSet;
 import java.util.concurrent.Executor;
 
 /**
@@ -50,74 +48,49 @@
     private static final String KEY_ASM_RESTRICTIONS_ENABLED = KEY_ASM_PREFIX
             + "asm_restrictions_enabled";
     private static final String KEY_ASM_TOASTS_ENABLED = KEY_ASM_PREFIX + "asm_toasts_enabled";
-    private static final String KEY_ASM_EXEMPTED_PACKAGES = KEY_ASM_PREFIX
-            + "asm_exempted_packages";
+
     private static final int VALUE_DISABLE = 0;
     private static final int VALUE_ENABLE_FOR_V = 1;
     private static final int VALUE_ENABLE_FOR_ALL = 2;
 
     private static final int DEFAULT_VALUE = VALUE_DISABLE;
-    private static final String DEFAULT_EXCEPTION_LIST = "";
 
     private static int sAsmToastsEnabled;
     private static int sAsmRestrictionsEnabled;
-    private static final HashSet<String> sExcludedPackageNames = new HashSet<>();
-    private static PackageManager sPm;
 
     @GuardedBy("ActivityTaskManagerService.mGlobalLock")
-    static void initialize(@NonNull Executor executor, @NonNull PackageManager pm) {
+    static void initialize(@NonNull Executor executor) {
         updateFromDeviceConfig();
         DeviceConfig.addOnPropertiesChangedListener(NAMESPACE, executor,
                 properties -> updateFromDeviceConfig());
-        sPm = pm;
     }
 
     @GuardedBy("ActivityTaskManagerService.mGlobalLock")
     static boolean shouldShowToast(int uid) {
-        return flagEnabledForUid(sAsmToastsEnabled, uid);
+        return sAsmToastsEnabled == VALUE_ENABLE_FOR_ALL
+                || (sAsmToastsEnabled == VALUE_ENABLE_FOR_V
+                        && CompatChanges.isChangeEnabled(ASM_RESTRICTIONS, uid));
     }
 
     @GuardedBy("ActivityTaskManagerService.mGlobalLock")
     static boolean shouldRestrictActivitySwitch(int uid) {
-        return flagEnabledForUid(sAsmRestrictionsEnabled, uid);
-    }
-
-    private static boolean flagEnabledForUid(int flag, int uid) {
-        boolean flagEnabled = flag == VALUE_ENABLE_FOR_ALL
-                || (flag == VALUE_ENABLE_FOR_V
-                    && CompatChanges.isChangeEnabled(ASM_RESTRICTIONS, uid));
-
-        if (flagEnabled) {
-            String[] packageNames = sPm.getPackagesForUid(uid);
-            if (packageNames == null) {
-                return true;
-            }
-            for (int i = 0; i < packageNames.length; i++) {
-                if (sExcludedPackageNames.contains(packageNames[i])) {
-                    return false;
-                }
-            }
-            return true;
+        if (android.security.Flags.asmRestrictionsEnabled()) {
+            return CompatChanges.isChangeEnabled(ASM_RESTRICTIONS, uid)
+                    || asmRestrictionsEnabledForAll();
         }
 
         return false;
     }
 
+    @GuardedBy("ActivityTaskManagerService.mGlobalLock")
+    static boolean asmRestrictionsEnabledForAll() {
+        return sAsmRestrictionsEnabled == VALUE_ENABLE_FOR_ALL;
+    }
+
     private static void updateFromDeviceConfig() {
         sAsmToastsEnabled = DeviceConfig.getInt(NAMESPACE, KEY_ASM_TOASTS_ENABLED,
                 DEFAULT_VALUE);
         sAsmRestrictionsEnabled = DeviceConfig.getInt(NAMESPACE, KEY_ASM_RESTRICTIONS_ENABLED,
                 DEFAULT_VALUE);
-
-        String rawExceptionList = DeviceConfig.getString(NAMESPACE,
-                KEY_ASM_EXEMPTED_PACKAGES, DEFAULT_EXCEPTION_LIST);
-        sExcludedPackageNames.clear();
-        String[] packages = rawExceptionList.split(",");
-        for (String packageName : packages) {
-            String packageNameTrimmed = packageName.trim();
-            if (!packageNameTrimmed.isEmpty()) {
-                sExcludedPackageNames.add(packageNameTrimmed);
-            }
-        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 0e6c06d..445295a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -881,7 +881,7 @@
             mTaskSupervisor.onSystemReady();
             mActivityClientController.onSystemReady();
             // TODO(b/258792202) Cleanup once ASM is ready to launch
-            ActivitySecurityModelFeatureFlags.initialize(mContext.getMainExecutor(), pm);
+            ActivitySecurityModelFeatureFlags.initialize(mContext.getMainExecutor());
             mGrammaticalManagerInternal = LocalServices.getService(
                     GrammaticalInflectionManagerInternal.class);
         }
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 2d6f03a..3bc5319 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -56,6 +56,7 @@
 import android.compat.annotation.EnabledAfter;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Process;
 import android.os.SystemClock;
@@ -529,6 +530,9 @@
         static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked");
         static final BalVerdict ALLOW_BY_DEFAULT =
                 new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default");
+        // Careful using this - it will bypass all ASM checks.
+        static final BalVerdict ALLOW_PRIVILEGED =
+                new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID, false, "PRIVILEGED");
         private final @BalCode int mCode;
         private final boolean mBackground;
         private final String mMessage;
@@ -1234,7 +1238,8 @@
         boolean shouldBlockActivityStart = ActivitySecurityModelFeatureFlags
                 .shouldRestrictActivitySwitch(callingUid);
         int[] finishCount = new int[0];
-        if (shouldBlockActivityStart) {
+        if (shouldBlockActivityStart
+                && blockCrossUidActivitySwitchFromBelowForActivity(targetTaskTop)) {
             ActivityRecord activity = targetTask.getActivity(isLaunchingOrLaunched);
             if (activity == null) {
                 // mStartActivity is not in task, so clear everything
@@ -1319,7 +1324,7 @@
 
         boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
                 .shouldRestrictActivitySwitch(callingUid)
-                && bas.mBlockActivityStartIfFlagEnabled;
+                        && bas.mBlockActivityStartIfFlagEnabled;
 
         PackageManager pm = mService.mContext.getPackageManager();
         String callingPackage = pm.getNameForUid(callingUid);
@@ -1373,19 +1378,19 @@
             int uid, @Nullable ActivityRecord sourceRecord) {
         // If the source is visible, consider it 'top'.
         if (sourceRecord != null && sourceRecord.isVisibleRequested()) {
-            return new BlockActivityStart(false, false);
+            return BlockActivityStart.ACTIVITY_START_ALLOWED;
         }
 
         // Always allow actual top activity to clear task
         ActivityRecord topActivity = task.getTopMostActivity();
         if (topActivity != null && topActivity.isUid(uid)) {
-            return new BlockActivityStart(false, false);
+            return BlockActivityStart.ACTIVITY_START_ALLOWED;
         }
 
         // If UID is visible in target task, allow launch
         if (task.forAllActivities((Predicate<ActivityRecord>)
                 ar -> ar.isUid(uid) && ar.isVisibleRequested())) {
-            return new BlockActivityStart(false, false);
+            return BlockActivityStart.ACTIVITY_START_ALLOWED;
         }
 
         // Consider the source activity, whether or not it is finishing. Do not consider any other
@@ -1452,12 +1457,11 @@
     private BlockActivityStart blockCrossUidActivitySwitchFromBelow(ActivityRecord ar,
             int sourceUid) {
         if (ar.isUid(sourceUid)) {
-            return new BlockActivityStart(false, false);
+            return BlockActivityStart.ACTIVITY_START_ALLOWED;
         }
 
-        // If mAllowCrossUidActivitySwitchFromBelow is set, honor it.
-        if (ar.mAllowCrossUidActivitySwitchFromBelow) {
-            return new BlockActivityStart(false, false);
+        if (!blockCrossUidActivitySwitchFromBelowForActivity(ar)) {
+            return BlockActivityStart.ACTIVITY_START_ALLOWED;
         }
 
         // At this point, we would block if the feature is launched and both apps were V+
@@ -1468,8 +1472,11 @@
                 ActivitySecurityModelFeatureFlags.shouldRestrictActivitySwitch(ar.getUid())
                         && ActivitySecurityModelFeatureFlags
                         .shouldRestrictActivitySwitch(sourceUid);
-        return new BackgroundActivityStartController
-                .BlockActivityStart(restrictActivitySwitch, true);
+        if (restrictActivitySwitch) {
+            return BlockActivityStart.BLOCK;
+        } else {
+            return BlockActivityStart.LOG_ONLY;
+        }
     }
 
     /**
@@ -1675,14 +1682,52 @@
         }
     }
 
-    static class BlockActivityStart {
+    /**
+     * Activity level allowCrossUidActivitySwitchFromBelow defaults to false.
+     * Package level defaults to true.
+     * We block the launch if dev has explicitly set package level to false, and activity level has
+     * not opted out
+     */
+    private boolean blockCrossUidActivitySwitchFromBelowForActivity(@NonNull ActivityRecord ar) {
+        // We don't need to check package level if activity has opted out.
+        if (ar.mAllowCrossUidActivitySwitchFromBelow) {
+            return false;
+        }
+
+        if (ActivitySecurityModelFeatureFlags.asmRestrictionsEnabledForAll()) {
+            return true;
+        }
+
+        String packageName = ar.packageName;
+        if (packageName == null) {
+            return false;
+        }
+
+        PackageManager pm = mService.mContext.getPackageManager();
+        ApplicationInfo applicationInfo;
+
+        try {
+            applicationInfo = pm.getApplicationInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.wtf(TAG, "Package name: " + packageName + " not found.");
+            return false;
+        }
+
+        return !applicationInfo.allowCrossUidActivitySwitchFromBelow;
+    }
+
+    private static class BlockActivityStart {
+        private static final BlockActivityStart ACTIVITY_START_ALLOWED =
+                new BlockActivityStart(false, false);
+        private static final BlockActivityStart LOG_ONLY = new BlockActivityStart(false, true);
+        private static final BlockActivityStart BLOCK = new BlockActivityStart(true, true);
         // We should block if feature flag is enabled
         private final boolean mBlockActivityStartIfFlagEnabled;
         // Used for logging/toasts. Would we block if target sdk was V and feature was
         // enabled?
         private final boolean mWouldBlockActivityStartIgnoringFlag;
 
-        BlockActivityStart(boolean shouldBlockActivityStart,
+        private BlockActivityStart(boolean shouldBlockActivityStart,
                 boolean wouldBlockActivityStartIgnoringFlags) {
             this.mBlockActivityStartIfFlagEnabled = shouldBlockActivityStart;
             this.mWouldBlockActivityStartIgnoringFlag = wouldBlockActivityStartIgnoringFlags;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 25a5fca..e743172 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6783,14 +6783,6 @@
         return mSandboxDisplayApis;
     }
 
-    /**
-     * For testing only; inject a ContentRecorder instance.
-     */
-    @VisibleForTesting
-    void setContentRecorder(ContentRecorder contentRecorder) {
-        mContentRecorder = contentRecorder;
-    }
-
     private ContentRecorder getContentRecorder() {
         if (mContentRecorder == null) {
             mContentRecorder = new ContentRecorder(this);
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index e6ef90b..68bff43 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_EMBEDDED_WINDOWS;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -34,6 +35,9 @@
 import android.view.InputChannel;
 import android.window.InputTransferToken;
 
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.input.InputManagerService;
+
 /**
  * Keeps track of embedded windows.
  *
@@ -52,9 +56,13 @@
     private final Object mGlobalLock;
     private final ActivityTaskManagerService mAtmService;
 
-    EmbeddedWindowController(ActivityTaskManagerService atmService) {
+    private final InputManagerService mInputManagerService;
+
+    EmbeddedWindowController(ActivityTaskManagerService atmService,
+            InputManagerService inputManagerService) {
         mAtmService = atmService;
         mGlobalLock = atmService.getGlobalLock();
+        mInputManagerService = inputManagerService;
     }
 
     /**
@@ -135,6 +143,60 @@
         return mWindowsByWindowToken.get(windowToken);
     }
 
+    private boolean isValidTouchGestureParams(WindowState hostWindowState,
+            EmbeddedWindow embeddedWindow) {
+        if (embeddedWindow == null) {
+            ProtoLog.w(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "Attempt to transfer touch gesture with non-existent embedded window");
+            return false;
+        }
+        final WindowState wsAssociatedWithEmbedded = embeddedWindow.getWindowState();
+        if (wsAssociatedWithEmbedded == null) {
+            ProtoLog.w(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "Attempt to transfer touch gesture using embedded window with no associated "
+                            + "host");
+            return false;
+        }
+        if (wsAssociatedWithEmbedded.mClient.asBinder() != hostWindowState.mClient.asBinder()) {
+            ProtoLog.w(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "Attempt to transfer touch gesture with host window not associated with "
+                            + "embedded window");
+            return false;
+        }
+
+        if (embeddedWindow.getInputChannelToken() == null) {
+            ProtoLog.w(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "Attempt to transfer touch gesture using embedded window that has no input "
+                            + "channel");
+            return false;
+        }
+        if (hostWindowState.mInputChannelToken == null) {
+            ProtoLog.w(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "Attempt to transfer touch gesture using a host window with no input channel");
+            return false;
+        }
+        return true;
+    }
+
+    boolean transferToHost(InputTransferToken embeddedWindowToken,
+            WindowState transferToHostWindowState) {
+        EmbeddedWindow ew = getByInputTransferToken(embeddedWindowToken);
+        if (!isValidTouchGestureParams(transferToHostWindowState, ew)) {
+            return false;
+        }
+        return mInputManagerService.transferTouchFocus(ew.getInputChannelToken(),
+                transferToHostWindowState.mInputChannelToken);
+    }
+
+    boolean transferToEmbedded(WindowState hostWindowState, InputTransferToken transferToToken) {
+        final EmbeddedWindowController.EmbeddedWindow ew = getByInputTransferToken(transferToToken);
+        if (!isValidTouchGestureParams(hostWindowState, ew)) {
+            return false;
+        }
+        return mInputManagerService.transferTouchFocus(hostWindowState.mInputChannelToken,
+                ew.getInputChannelToken());
+    }
+
     static class EmbeddedWindow implements InputTarget {
         final IBinder mClient;
         @Nullable final WindowState mHostWindowState;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 609ad1e..bf45804 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -612,10 +612,8 @@
     }
 
     void refreshSecureSurfaceState() {
-        forAllWindows((w) -> {
-            if (w.mHasSurface) {
-                w.setSecureLocked(w.isSecureLocked());
-            }
+        forAllWindows(w -> {
+            w.setSecureLocked(w.isSecureLocked());
         }, true /* traverseTopToBottom */);
     }
 
diff --git a/services/core/java/com/android/server/wm/SensitiveContentPackages.java b/services/core/java/com/android/server/wm/SensitiveContentPackages.java
index a7d6903b..5fe48d1 100644
--- a/services/core/java/com/android/server/wm/SensitiveContentPackages.java
+++ b/services/core/java/com/android/server/wm/SensitiveContentPackages.java
@@ -56,6 +56,17 @@
     }
 
     /**
+     * Clears apps added to collection of apps in which screen capture should be disabled.
+     *
+     * @param packageInfos set of {@link PackageInfo} whose windows should be unblocked
+     *                     from capture.
+     * @return {@code true} if packages set is modified, {@code false} otherwise.
+     */
+    public boolean removeBlockScreenCaptureForApps(@NonNull ArraySet<PackageInfo> packageInfos) {
+        return mProtectedPackages.removeAll(packageInfos);
+    }
+
+    /**
      * Clears the set of package/uid pairs that should be blocked from screen capture
      *
      * @return {@code true} if packages set is modified, {@code false} otherwise.
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 3c8c55e..975208f 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -970,40 +970,6 @@
     }
 
     @Override
-    public boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow) {
-        if (embeddedWindow == null) {
-            return false;
-        }
-
-        final long identity = Binder.clearCallingIdentity();
-        boolean didTransfer = false;
-        try {
-            didTransfer = mService.transferEmbeddedTouchFocusToHost(embeddedWindow);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        return didTransfer;
-    }
-
-    @Override
-    public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
-            InputTransferToken inputTransferToken) {
-        if (hostWindow == null) {
-            return false;
-        }
-
-        final long identity = Binder.clearCallingIdentity();
-        boolean didTransfer;
-        try {
-            didTransfer = mService.transferHostTouchGestureToEmbedded(this, hostWindow,
-                    inputTransferToken);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        return didTransfer;
-    }
-
-    @Override
     public boolean moveFocusToAdjacentWindow(IWindow fromWindow, @FocusDirection int direction) {
         final long identity = Binder.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index ae4c3b9..669c61c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -1043,6 +1043,15 @@
     /**
      * Clears apps added to collection of apps in which screen capture should be disabled.
      *
+     * @param packageInfos set of {@link PackageInfo} whose windows should be unblocked
+     *                     from capture.
+     */
+    public abstract void removeBlockScreenCaptureForApps(
+            @NonNull ArraySet<PackageInfo> packageInfos);
+
+    /**
+     * Clears all apps added to collection of apps in which screen capture should be disabled.
+     *
      * <p> This clears and resets any existing set or added applications from
      * * {@link #addBlockScreenCaptureForApps(ArraySet)}
      */
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 631ebcd..3d6bd4f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -101,6 +101,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_EMBEDDED_WINDOWS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
@@ -1344,7 +1345,7 @@
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
         LocalServices.addService(
                 ImeTargetVisibilityPolicy.class, new ImeTargetVisibilityPolicyImpl());
-        mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
+        mEmbeddedWindowController = new EmbeddedWindowController(mAtmService, inputManager);
 
         mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
                 mContext.getResources());
@@ -8632,6 +8633,17 @@
         }
 
         @Override
+        public void removeBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) {
+            synchronized (mGlobalLock) {
+                boolean modified =
+                        mSensitiveContentPackages.removeBlockScreenCaptureForApps(packageInfos);
+                if (modified) {
+                    WindowManagerService.this.refreshScreenCaptureDisabled();
+                }
+            }
+        }
+
+        @Override
         public void clearBlockedApps() {
             synchronized (mGlobalLock) {
                 boolean modified = mSensitiveContentPackages.clearBlockedApps();
@@ -9044,73 +9056,37 @@
                 null /* region */, clientToken);
     }
 
-    boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow) {
-        final IBinder windowBinder = embeddedWindow.asBinder();
-        final IBinder hostInputChannel, embeddedInputChannel;
-        synchronized (mGlobalLock) {
-            final EmbeddedWindowController.EmbeddedWindow ew =
-                mEmbeddedWindowController.getByWindowToken(windowBinder);
-            if (ew == null) {
-                Slog.w(TAG, "Attempt to transfer touch focus from non-existent embedded window");
-                return false;
-            }
-            final WindowState hostWindowState = ew.getWindowState();
-            if (hostWindowState == null) {
-                Slog.w(TAG, "Attempt to transfer touch focus from embedded window with no" +
-                    " associated host");
-                return false;
-            }
-            embeddedInputChannel = ew.getInputChannelToken();
-            if (embeddedInputChannel == null) {
-                Slog.w(TAG, "Attempt to transfer touch focus from embedded window with no input" +
-                    " channel");
-                return false;
-            }
-            hostInputChannel = hostWindowState.mInputChannelToken;
-            if (hostInputChannel == null) {
-                Slog.w(TAG, "Attempt to transfer touch focus to a host window with no" +
-                    " input channel");
-                return false;
-            }
-            return mInputManager.transferTouchFocus(embeddedInputChannel, hostInputChannel);
+    @Override
+    public boolean transferTouchGesture(InputTransferToken transferFromToken,
+            InputTransferToken transferToToken) {
+        if (transferFromToken == null || transferToToken == null) {
+            ProtoLog.e(WM_DEBUG_EMBEDDED_WINDOWS,
+                    "transferTouchGesture failed because args transferFromToken or "
+                            + "transferToToken is null");
+            return false;
         }
-    }
 
-    boolean transferHostTouchGestureToEmbedded(Session session, IWindow hostWindow,
-            InputTransferToken inputTransferToken) {
-        final IBinder hostInputChannel, embeddedInputChannel;
-        synchronized (mGlobalLock) {
-            final WindowState hostWindowState = windowForClientLocked(session, hostWindow, false);
-            if (hostWindowState == null) {
-                Slog.w(TAG, "Attempt to transfer touch gesture with invalid host window");
-                return false;
+        final long identity = Binder.clearCallingIdentity();
+        boolean didTransfer;
+        try {
+            synchronized (mGlobalLock) {
+                // If the transferToToken exists in the input to window map, it means the request
+                // is to transfer from embedded to host. Otherwise, the transferToToken
+                // represents an embedded window so transfer from host to embedded.
+                WindowState windowStateTo = mInputToWindowMap.get(transferToToken.mToken);
+                if (windowStateTo != null) {
+                    didTransfer = mEmbeddedWindowController.transferToHost(transferFromToken,
+                            windowStateTo);
+                } else {
+                    WindowState windowStateFrom = mInputToWindowMap.get(transferFromToken.mToken);
+                    didTransfer = mEmbeddedWindowController.transferToEmbedded(windowStateFrom,
+                            transferToToken);
+                }
             }
-
-            final EmbeddedWindowController.EmbeddedWindow ew =
-                    mEmbeddedWindowController.getByInputTransferToken(inputTransferToken);
-            if (ew == null || ew.mHostWindowState == null) {
-                Slog.w(TAG, "Attempt to transfer touch gesture to non-existent embedded window");
-                return false;
-            }
-            if (ew.mHostWindowState.mClient.asBinder() != hostWindow.asBinder()) {
-                Slog.w(TAG, "Attempt to transfer touch gesture to embedded window not associated"
-                        + " with host window");
-                return false;
-            }
-            embeddedInputChannel = ew.getInputChannelToken();
-            if (embeddedInputChannel == null) {
-                Slog.w(TAG, "Attempt to transfer touch focus from embedded window with no input"
-                        + " channel");
-                return false;
-            }
-            hostInputChannel = hostWindowState.mInputChannelToken;
-            if (hostInputChannel == null) {
-                Slog.w(TAG,
-                        "Attempt to transfer touch focus to a host window with no input channel");
-                return false;
-            }
-            return mInputManager.transferTouchFocus(hostInputChannel, embeddedInputChannel);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
+        return didTransfer;
     }
 
     private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e619440..9b84f39 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -29,9 +29,11 @@
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_APP_RESTRICTIONS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_AUTOFILL;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_BLUETOOTH;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CALLS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION;
@@ -50,6 +52,7 @@
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MICROPHONE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE;
@@ -74,6 +77,7 @@
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_TIME;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING;
@@ -21984,6 +21988,20 @@
     }
 
     @Override
+    public boolean isTheftDetectionTriggered(String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(callerPackageName);
+        if (!android.app.admin.flags.Flags.deviceTheftImplEnabled()) {
+            return false;
+        }
+        enforcePermission(MANAGE_DEVICE_POLICY_THEFT_DETECTION, caller.getPackageName(),
+                caller.getUserId());
+
+        //STOPSHIP: replace 1<<9 with
+        // LockPatternUtils.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST once ag/26042068 lands
+        return 0 != (mLockPatternUtils.getStrongAuthForUser(caller.getUserId()) & (1 << 9));
+    }
+
+    @Override
     public void setWifiSsidPolicy(String callerPackageName, WifiSsidPolicy policy) {
         CallerIdentity caller;
 
@@ -22424,14 +22442,6 @@
         });
     }
 
-    // Permission that will need to be created in V.
-    private static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL =
-            "manage_device_policy_block_uninstall";
-    private static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE =
-            "manage_device_policy_camera_toggle";
-    private static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE =
-            "manage_device_policy_microphone_toggle";
-
     // DPC types
     private static final int NOT_A_DPC = -1;
     private static final int DEFAULT_DEVICE_OWNER = 0;
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
index bf2619b..42e41d5 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
@@ -18,8 +18,8 @@
 
 import static android.hardware.SensorManager.SENSOR_DELAY_FASTEST;
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.TYPE_EXTERNAL;
 
@@ -478,7 +478,8 @@
         }
 
         public static DeviceStateConfiguration createConfig(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
                 @NonNull String name,
                 @DeviceState.DeviceStateFlags int flags,
                 @NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
@@ -488,7 +489,8 @@
         }
 
         public static DeviceStateConfiguration createConfig(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
                 @NonNull String name,
                 @NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
         ) {
@@ -498,7 +500,8 @@
 
         /** Create a configuration with availability predicate **/
         public static DeviceStateConfiguration createConfig(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
                 @NonNull String name,
                 @DeviceState.DeviceStateFlags int flags,
                 @NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate,
@@ -543,7 +546,8 @@
          * @return device state configuration
          */
         public static DeviceStateConfiguration createTentModeClosedState(
-                @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+                @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+                        MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
                 @NonNull String name,
                 @DeviceState.DeviceStateFlags int flags,
                 int minClosedAngleDegrees,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 14e4481..ee758db 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -107,6 +107,7 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockSettingsInternal;
+import com.android.server.adaptiveauth.AdaptiveAuthService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.appbinding.AppBindingService;
 import com.android.server.appop.AppOpMigrationHelper;
@@ -2615,6 +2616,12 @@
             mSystemServiceManager.startService(AuthService.class);
             t.traceEnd();
 
+            if (android.adaptiveauth.Flags.enableAdaptiveAuth()) {
+                t.traceBegin("StartAdaptiveAuthService");
+                mSystemServiceManager.startService(AdaptiveAuthService.class);
+                t.traceEnd();
+            }
+
             if (!isWatch) {
                 // We don't run this on watches as there are no plans to use the data logged
                 // on watch devices.
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 5588276..cb3ee73 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -46,6 +46,7 @@
 import com.android.server.pm.parsing.PackageInfoUtils
 import com.android.server.pm.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageState
+import libcore.util.EmptyArray
 
 class AppIdPermissionPolicy : SchemePolicy() {
     private val persistence = AppIdPermissionPersistence()
@@ -73,40 +74,42 @@
     }
 
     override fun MutateStateScope.onInitialized() {
-        newState.externalState.configPermissions.forEach { (permissionName, permissionEntry) ->
-            val oldPermission = newState.systemState.permissions[permissionName]
-            val newPermission =
-                if (oldPermission != null) {
-                    if (permissionEntry.gids != null) {
-                        oldPermission.copy(
-                            gids = permissionEntry.gids,
-                            areGidsPerUser = permissionEntry.perUser
-                        )
-                    } else {
-                        return@forEach
-                    }
-                } else {
-                    @Suppress("DEPRECATION")
-                    val permissionInfo =
-                        PermissionInfo().apply {
-                            name = permissionName
-                            packageName = PLATFORM_PACKAGE_NAME
-                            protectionLevel = PermissionInfo.PROTECTION_SIGNATURE
+        if (!Flags.newPermissionGidEnabled()) {
+            newState.externalState.configPermissions.forEach { (permissionName, permissionEntry) ->
+                val oldPermission = newState.systemState.permissions[permissionName]
+                val newPermission =
+                    if (oldPermission != null) {
+                        if (permissionEntry.gids != null) {
+                            oldPermission.copy(
+                                gids = permissionEntry.gids,
+                                areGidsPerUser = permissionEntry.perUser
+                            )
+                        } else {
+                            return@forEach
                         }
-                    if (permissionEntry.gids != null) {
-                        Permission(
-                            permissionInfo,
-                            false,
-                            Permission.TYPE_CONFIG,
-                            0,
-                            permissionEntry.gids,
-                            permissionEntry.perUser
-                        )
                     } else {
-                        Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0)
+                        @Suppress("DEPRECATION")
+                        val permissionInfo =
+                            PermissionInfo().apply {
+                                name = permissionName
+                                packageName = PLATFORM_PACKAGE_NAME
+                                protectionLevel = PermissionInfo.PROTECTION_SIGNATURE
+                            }
+                        if (permissionEntry.gids != null) {
+                            Permission(
+                                permissionInfo,
+                                false,
+                                Permission.TYPE_CONFIG,
+                                0,
+                                permissionEntry.gids,
+                                permissionEntry.perUser
+                            )
+                        } else {
+                            Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0)
+                        }
                     }
-                }
-            newState.mutateSystemState().mutatePermissions()[permissionName] = newPermission
+                newState.mutateSystemState().mutatePermissions()[permissionName] = newPermission
+            }
         }
     }
 
@@ -459,7 +462,7 @@
                 )
                 return@forEachIndexed
             }
-            val newPermission =
+            var newPermission =
                 if (oldPermission != null && newPackageName != oldPermission.packageName) {
                     val oldPackageName = oldPermission.packageName
                     // Only allow system apps to redefine non-system permissions.
@@ -582,6 +585,24 @@
                         )
                     }
                 }
+            if (Flags.newPermissionGidEnabled()) {
+                var gids = EmptyArray.INT
+                var areGidsPerUser = false
+                if (!parsedPermission.isTree && packageState.isSystem) {
+                    newState.externalState.configPermissions[permissionName]?.let {
+                        gids = it.gids
+                        areGidsPerUser = it.perUser
+                    }
+                }
+                newPermission = Permission(
+                    newPermissionInfo,
+                    true,
+                    Permission.TYPE_MANIFEST,
+                    packageState.appId,
+                    gids,
+                    areGidsPerUser
+                )
+            }
 
             if (parsedPermission.isTree) {
                 newState.mutateSystemState().mutatePermissionTrees()[permissionName] = newPermission
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 67f66de..0704c8f 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -466,7 +466,7 @@
         return size
     }
 
-    override fun checkUidPermission(uid: Int, permissionName: String, deviceId: Int): Int {
+    override fun checkUidPermission(uid: Int, permissionName: String, deviceId: String): Int {
         val userId = UserHandle.getUserId(uid)
         if (!userManagerInternal.exists(userId)) {
             return PackageManager.PERMISSION_DENIED
@@ -489,15 +489,9 @@
                 return PackageManager.PERMISSION_DENIED
             }
 
-            val persistentDeviceId = getPersistentDeviceId(deviceId)
-            if (persistentDeviceId == null) {
-                Slog.e(LOG_TAG, "Cannot find persistent device id for $deviceId.")
-                return PackageManager.PERMISSION_DENIED
-            }
-
             val isPermissionGranted =
                 service.getState {
-                    isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)
+                    isPermissionGranted(packageState, userId, permissionName, deviceId)
                 }
             return if (isPermissionGranted) {
                 PackageManager.PERMISSION_GRANTED
@@ -531,7 +525,7 @@
     override fun checkPermission(
         packageName: String,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int
     ): Int {
         if (!userManagerInternal.exists(userId)) {
@@ -545,9 +539,7 @@
                 ?: return PackageManager.PERMISSION_DENIED
 
         val isPermissionGranted =
-            service.getState {
-                isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)
-            }
+            service.getState { isPermissionGranted(packageState, userId, permissionName, deviceId) }
         return if (isPermissionGranted) {
             PackageManager.PERMISSION_GRANTED
         } else {
@@ -565,21 +557,13 @@
         packageState: PackageState,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String
+        deviceId: String
     ): Boolean {
         val appId = packageState.appId
         // Note that instant apps can't have shared UIDs, so we only need to check the current
         // package state.
         val isInstantApp = packageState.getUserStateOrDefault(userId).isInstantApp
-        if (
-            isSinglePermissionGranted(
-                appId,
-                userId,
-                isInstantApp,
-                permissionName,
-                persistentDeviceId
-            )
-        ) {
+        if (isSinglePermissionGranted(appId, userId, isInstantApp, permissionName, deviceId)) {
             return true
         }
 
@@ -591,7 +575,7 @@
                     userId,
                     isInstantApp,
                     fullerPermissionName,
-                    persistentDeviceId
+                    deviceId
                 )
         ) {
             return true
@@ -606,9 +590,9 @@
         userId: Int,
         isInstantApp: Boolean,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
     ): Boolean {
-        val flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
+        val flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
         if (!PermissionFlags.isPermissionGranted(flags)) {
             return false
         }
@@ -689,22 +673,16 @@
     override fun grantRuntimePermission(
         packageName: String,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int
     ) {
-        setRuntimePermissionGranted(
-            packageName,
-            userId,
-            permissionName,
-            persistentDeviceId,
-            isGranted = true
-        )
+        setRuntimePermissionGranted(packageName, userId, permissionName, deviceId, isGranted = true)
     }
 
     override fun revokeRuntimePermission(
         packageName: String,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int,
         reason: String?
     ) {
@@ -712,7 +690,7 @@
             packageName,
             userId,
             permissionName,
-            persistentDeviceId,
+            deviceId,
             isGranted = false,
             revokeReason = reason
         )
@@ -740,7 +718,7 @@
         packageName: String,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         isGranted: Boolean,
         skipKillUid: Boolean = false,
         revokeReason: String? = null
@@ -765,7 +743,7 @@
                     (if (isGranted) "" else "skipKillUid = $skipKillUid, reason = $revokeReason") +
                     ", userId = $userId," +
                     " callingUid = $callingUidName ($callingUid))," +
-                    " persistentDeviceId = $persistentDeviceId",
+                    " deviceId = $deviceId",
                 RuntimeException()
             )
         }
@@ -835,7 +813,7 @@
                 packageState,
                 userId,
                 permissionName,
-                persistentDeviceId,
+                deviceId,
                 isGranted,
                 canManageRolePermission,
                 overridePolicyFixed,
@@ -923,7 +901,7 @@
         packageState: PackageState,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         isGranted: Boolean,
         canManageRolePermission: Boolean,
         overridePolicyFixed: Boolean,
@@ -982,8 +960,7 @@
         }
 
         val appId = packageState.appId
-        val oldFlags =
-            getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
+        val oldFlags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
 
         if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) {
             if (reportError) {
@@ -1055,7 +1032,7 @@
             return
         }
 
-        setPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId, newFlags)
+        setPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId, newFlags)
 
         if (permission.isRuntime) {
             val action =
@@ -1089,7 +1066,7 @@
     override fun getPermissionFlags(
         packageName: String,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int,
     ): Int {
         if (!userManagerInternal.exists(userId)) {
@@ -1125,12 +1102,7 @@
             }
 
             val flags =
-                getPermissionFlagsWithPolicy(
-                    packageState.appId,
-                    userId,
-                    permissionName,
-                    persistentDeviceId
-                )
+                getPermissionFlagsWithPolicy(packageState.appId, userId, permissionName, deviceId)
 
             return PermissionFlags.toApiFlags(flags)
         }
@@ -1138,7 +1110,7 @@
 
     override fun getAllPermissionStates(
         packageName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int
     ): Map<String, PermissionState> {
         if (!userManagerInternal.exists(userId)) {
@@ -1165,14 +1137,15 @@
 
         val permissionFlagsMap =
             service.getState {
-                if (persistentDeviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT) {
+                if (deviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT) {
                     with(policy) { getAllPermissionFlags(packageState.appId, userId) }
                 } else {
                     with(devicePolicy) {
-                        getAllPermissionFlags(packageState.appId, persistentDeviceId, userId)
+                        getAllPermissionFlags(packageState.appId, deviceId, userId)
                     }
                 }
-            } ?: return emptyMap()
+            }
+                ?: return emptyMap()
 
         val permissionStates = ArrayMap<String, PermissionState>()
         permissionFlagsMap.forEachIndexed { _, permissionName, flags ->
@@ -1186,7 +1159,7 @@
     override fun isPermissionRevokedByPolicy(
         packageName: String,
         permissionName: String,
-        deviceId: Int,
+        deviceId: String,
         userId: Int
     ): Boolean {
         if (!userManagerInternal.exists(userId)) {
@@ -1207,24 +1180,13 @@
             }
                 ?: return false
 
-        val persistentDeviceId = getPersistentDeviceId(deviceId)
-        if (persistentDeviceId == null) {
-            Slog.w(LOG_TAG, "Cannot find persistent device Id for $deviceId")
-            return false
-        }
-
         service.getState {
-            if (isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)) {
+            if (isPermissionGranted(packageState, userId, permissionName, deviceId)) {
                 return false
             }
 
             val flags =
-                getPermissionFlagsWithPolicy(
-                    packageState.appId,
-                    userId,
-                    permissionName,
-                    persistentDeviceId
-                )
+                getPermissionFlagsWithPolicy(packageState.appId, userId, permissionName, deviceId)
 
             return flags.hasBits(PermissionFlags.POLICY_FIXED)
         }
@@ -1248,7 +1210,7 @@
     override fun shouldShowRequestPermissionRationale(
         packageName: String,
         permissionName: String,
-        deviceId: Int,
+        deviceId: String,
         userId: Int,
     ): Boolean {
         if (!userManagerInternal.exists(userId)) {
@@ -1274,19 +1236,13 @@
             return false
         }
 
-        val persistentDeviceId = getPersistentDeviceId(deviceId)
-        if (persistentDeviceId == null) {
-            Slog.w(LOG_TAG, "Cannot find persistent device Id for $deviceId")
-            return false
-        }
-
         val flags: Int
         service.getState {
-            if (isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)) {
+            if (isPermissionGranted(packageState, userId, permissionName, deviceId)) {
                 return false
             }
 
-            flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
+            flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
         }
         if (flags.hasAnyBit(UNREQUESTABLE_MASK)) {
             return false
@@ -1325,7 +1281,7 @@
         flagMask: Int,
         flagValues: Int,
         enforceAdjustPolicyPermission: Boolean,
-        persistentDeviceId: String,
+        deviceId: String,
         userId: Int
     ) {
         val callingUid = Binder.getCallingUid()
@@ -1351,7 +1307,7 @@
                 "updatePermissionFlags(packageName = $packageName," +
                     " permissionName = $permissionName, flagMask = $flagMaskString," +
                     " flagValues = $flagValuesString, userId = $userId," +
-                    " persistentDeviceId = $persistentDeviceId," +
+                    " deviceId = $deviceId," +
                     " callingUid = $callingUidName ($callingUid))",
                 RuntimeException()
             )
@@ -1441,7 +1397,7 @@
                 appId,
                 userId,
                 permissionName,
-                persistentDeviceId,
+                deviceId,
                 flagMask,
                 flagValues,
                 canUpdateSystemFlags,
@@ -1527,7 +1483,7 @@
         appId: Int,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         flagMask: Int,
         flagValues: Int,
         canUpdateSystemFlags: Boolean,
@@ -1561,8 +1517,7 @@
             return
         }
 
-        val oldFlags =
-            getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
+        val oldFlags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
         if (!isPermissionRequested && oldFlags == 0) {
             Slog.w(
                 LOG_TAG,
@@ -1573,7 +1528,7 @@
         }
 
         val newFlags = PermissionFlags.updateFlags(permission, oldFlags, flagMask, flagValues)
-        setPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId, newFlags)
+        setPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId, newFlags)
     }
 
     override fun getAllowlistedRestrictedPermissions(
@@ -1648,11 +1603,11 @@
         appId: Int,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
     ): Int {
         return if (
             !Flags.deviceAwarePermissionApisEnabled() ||
-                persistentDeviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+                deviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
         ) {
             with(policy) { getPermissionFlags(appId, userId, permissionName) }
         } else {
@@ -1664,9 +1619,7 @@
                 )
                 return with(policy) { getPermissionFlags(appId, userId, permissionName) }
             }
-            with(devicePolicy) {
-                getPermissionFlags(appId, persistentDeviceId, userId, permissionName)
-            }
+            with(devicePolicy) { getPermissionFlags(appId, deviceId, userId, permissionName) }
         }
     }
 
@@ -1674,12 +1627,12 @@
         appId: Int,
         userId: Int,
         permissionName: String,
-        persistentDeviceId: String,
+        deviceId: String,
         flags: Int
     ): Boolean {
         return if (
             !Flags.deviceAwarePermissionApisEnabled() ||
-                persistentDeviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+                deviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
         ) {
             with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
         } else {
@@ -1693,23 +1646,11 @@
             }
 
             with(devicePolicy) {
-                setPermissionFlags(appId, persistentDeviceId, userId, permissionName, flags)
+                setPermissionFlags(appId, deviceId, userId, permissionName, flags)
             }
         }
     }
 
-    private fun getPersistentDeviceId(deviceId: Int): String? {
-        if (deviceId == Context.DEVICE_ID_DEFAULT) {
-            return VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
-        }
-
-        if (virtualDeviceManagerInternal == null) {
-            virtualDeviceManagerInternal =
-                LocalServices.getService(VirtualDeviceManagerInternal::class.java)
-        }
-        return virtualDeviceManagerInternal?.getPersistentIdForDevice(deviceId)
-    }
-
     /**
      * This method does not enforce checks on the caller, should only be called after required
      * checks.
@@ -2270,9 +2211,9 @@
 
                     userState.appIdDevicePermissionFlags[appId]?.forEachIndexed {
                         _,
-                        persistentDeviceId,
+                        deviceId,
                         devicePermissionFlags ->
-                        println("Permissions (Device $persistentDeviceId):")
+                        println("Permissions (Device $deviceId):")
                         withIndent {
                             devicePermissionFlags.forEachIndexed { _, permissionName, flags ->
                                 val isGranted = PermissionFlags.isPermissionGranted(flags)
@@ -2415,9 +2356,8 @@
                 with(devicePolicy) { trimDevicePermissionStates(persistentDeviceIds) }
             }
         }
-        virtualDeviceManagerInternal?.registerPersistentDeviceIdRemovedListener { persistentDeviceId
-            ->
-            service.mutateState { with(devicePolicy) { onDeviceIdRemoved(persistentDeviceId) } }
+        virtualDeviceManagerInternal?.registerPersistentDeviceIdRemovedListener { deviceId ->
+            service.mutateState { with(devicePolicy) { onDeviceIdRemoved(deviceId) } }
         }
 
         permissionControllerManager =
@@ -2764,7 +2704,7 @@
         override fun onDevicePermissionFlagsChanged(
             appId: Int,
             userId: Int,
-            persistentDeviceId: String,
+            deviceId: String,
             permissionName: String,
             oldFlags: Int,
             newFlags: Int
@@ -2787,8 +2727,7 @@
                         permissionName in NOTIFICATIONS_PERMISSIONS &&
                             runtimePermissionRevokedUids.get(uid, true)
                 }
-                runtimePermissionChangedUidDevices.getOrPut(uid) { mutableSetOf() } +=
-                    persistentDeviceId
+                runtimePermissionChangedUidDevices.getOrPut(uid) { mutableSetOf() } += deviceId
             }
 
             if (permission.hasGids && !wasPermissionGranted && isPermissionGranted) {
@@ -2803,8 +2742,8 @@
             }
 
             runtimePermissionChangedUidDevices.forEachIndexed { _, uid, persistentDeviceIds ->
-                persistentDeviceIds.forEach { persistentDeviceId ->
-                    onPermissionsChangeListeners.onPermissionsChanged(uid, persistentDeviceId)
+                persistentDeviceIds.forEach { deviceId ->
+                    onPermissionsChangeListeners.onPermissionsChanged(uid, deviceId)
                 }
             }
             runtimePermissionChangedUidDevices.clear()
@@ -2844,8 +2783,11 @@
 
         private fun isAppBackupAndRestoreRunning(uid: Int): Boolean {
             if (
-                checkUidPermission(uid, Manifest.permission.BACKUP, Context.DEVICE_ID_DEFAULT) !=
-                    PackageManager.PERMISSION_GRANTED
+                checkUidPermission(
+                    uid,
+                    Manifest.permission.BACKUP,
+                    VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+                ) != PackageManager.PERMISSION_GRANTED
             ) {
                 return false
             }
@@ -2879,16 +2821,16 @@
             when (msg.what) {
                 MSG_ON_PERMISSIONS_CHANGED -> {
                     val uid = msg.arg1
-                    val persistentDeviceId = msg.obj as String
-                    handleOnPermissionsChanged(uid, persistentDeviceId)
+                    val deviceId = msg.obj as String
+                    handleOnPermissionsChanged(uid, deviceId)
                 }
             }
         }
 
-        private fun handleOnPermissionsChanged(uid: Int, persistentDeviceId: String) {
+        private fun handleOnPermissionsChanged(uid: Int, deviceId: String) {
             listeners.broadcast { listener ->
                 try {
-                    listener.onPermissionsChanged(uid, persistentDeviceId)
+                    listener.onPermissionsChanged(uid, deviceId)
                 } catch (e: RemoteException) {
                     Slog.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e)
                 }
@@ -2903,9 +2845,9 @@
             listeners.unregister(listener)
         }
 
-        fun onPermissionsChanged(uid: Int, persistentDeviceId: String) {
+        fun onPermissionsChanged(uid: Int, deviceId: String) {
             if (listeners.registeredCallbackCount > 0) {
-                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0, persistentDeviceId).sendToTarget()
+                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0, deviceId).sendToTarget()
             }
         }
 
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
index bd86fe2..f15e533 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
@@ -32,8 +32,6 @@
         "androidx.test.runner",
         "truth",
         "Harrier",
-        "frameworks-base-testutils",
-        "services.core",
     ],
     platform_apis: true,
     certificate: "platform",
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/AppEnumerationInternalTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/AppEnumerationInternalTests.java
index c615823..4012d8e 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/AppEnumerationInternalTests.java
+++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/AppEnumerationInternalTests.java
@@ -16,36 +16,32 @@
 
 package com.android.server.pm.test.appenumeration;
 
+import static android.content.Context.MEDIA_PROJECTION_SERVICE;
+
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.MockitoAnnotations.initMocks;
-
-import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.pm.IPackageManager;
 import android.content.pm.ProviderInfo;
+import android.media.projection.IMediaProjectionManager;
 import android.media.projection.MediaProjectionManager;
 import android.os.Process;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.util.test.LocalServiceKeeperRule;
-import com.android.server.media.projection.MediaProjectionManagerService;
-
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -77,17 +73,9 @@
 
     private IPackageManager mIPackageManager;
 
-    @Rule
-    public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();
-
-    @Mock private ActivityManagerInternal mActivityManagerInternal;
-
     @Before
     public void setup() {
-        initMocks(this);
         mIPackageManager = AppGlobals.getPackageManager();
-        mLocalServiceKeeperRule.overrideLocalService(ActivityManagerInternal.class,
-                mActivityManagerInternal);
     }
 
     @After
@@ -181,11 +169,11 @@
     public void mediaProjectionManager_createProjection_canSeeForceQueryable()
             throws Exception {
         installPackage(SHARED_USER_APK_PATH, true /* forceQueryable */);
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        final MediaProjectionManagerService mediaProjectionManager =
-                new MediaProjectionManagerService(context);
+        final IMediaProjectionManager mediaProjectionManager =
+                IMediaProjectionManager.Stub.asInterface(
+                        ServiceManager.getService(MEDIA_PROJECTION_SERVICE));
 
-        assertThat(mediaProjectionManager.createProjectionInternal(0 /* uid */, TARGET_SHARED_USER,
+        assertThat(mediaProjectionManager.createProjection(0 /* uid */, TARGET_SHARED_USER,
                 MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */))
                 .isNotNull();
     }
@@ -193,13 +181,12 @@
     @Test
     public void mediaProjectionManager_createProjection_cannotSeeTarget() {
         installPackage(SHARED_USER_APK_PATH, false /* forceQueryable */);
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        final MediaProjectionManagerService mediaProjectionManager =
-                new MediaProjectionManagerService(context);
+        final IMediaProjectionManager mediaProjectionManager =
+                IMediaProjectionManager.Stub.asInterface(
+                        ServiceManager.getService(MEDIA_PROJECTION_SERVICE));
 
         Assert.assertThrows(IllegalArgumentException.class,
-                () -> mediaProjectionManager.createProjectionInternal(0 /* uid */,
-                        TARGET_SHARED_USER,
+                () -> mediaProjectionManager.createProjection(0 /* uid */, TARGET_SHARED_USER,
                         MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */));
     }
 
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index cfe701f..d4b57f1 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -273,7 +273,8 @@
         AndroidPackage::hasRequestForegroundServiceExemption,
         AndroidPackage::hasRequestRawExternalStorageAccess,
         AndroidPackage::isUpdatableSystem,
-        AndroidPackage::getEmergencyInstaller
+        AndroidPackage::getEmergencyInstaller,
+        AndroidPackage::isAllowCrossUidActivitySwitchFromBelow,
     )
 
     override fun extraParams() = listOf(
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index d876dae..47928bc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -72,6 +72,8 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalAnswers.answer;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
@@ -157,9 +159,11 @@
     private static final int MOCKAPP2_UID_OTHER = MOCKAPP2_UID + UserHandle.PER_USER_RANGE;
     private static final int MOCKAPP_ISOLATED_UID = Process.FIRST_ISOLATED_UID + 321;
     private static final String MOCKAPP_ISOLATED_PROCESSNAME = "isolated test #1";
+    private static final int MOCKAPP_SDK_SANDBOX_UID = Process.FIRST_SDK_SANDBOX_UID + 654;
+    private static final String MOCKAPP_SDK_SANDBOX_PROCESSNAME = "sandbox test #1";
 
     private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
-                                          + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+            + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
     private static Context sContext;
     private static PackageManagerInternal sPackageManagerInternal;
     private static ActivityManagerService sService;
@@ -271,7 +275,6 @@
 
     /**
      * Replace the process LRU with the given processes.
-     * @param apps
      */
     @SuppressWarnings("GuardedBy")
     private void setProcessesToLru(ProcessRecord... apps) {
@@ -660,7 +663,7 @@
             app.mState.setLastTopTime(nowUptime);
             // Simulate the system starting and binding to a service in the app.
             ServiceRecord s = bindService(app, system,
-                    null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+                    null, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
             s.lastTopAlmostPerceptibleBindRequestUptimeMs = nowUptime;
             s.getConnections().clear();
             app.mServices.updateHasTopStartedAlmostPerceptibleServices();
@@ -682,7 +685,7 @@
             app.mState.setLastTopTime(nowUptime);
             // Simulate the system starting and binding to a service in the app.
             ServiceRecord s = bindService(app, system,
-                    null, Context.BIND_ALMOST_PERCEPTIBLE + 2, mock(IBinder.class));
+                    null, null, Context.BIND_ALMOST_PERCEPTIBLE + 2, mock(IBinder.class));
             s.lastTopAlmostPerceptibleBindRequestUptimeMs =
                     nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
             app.mServices.updateHasTopStartedAlmostPerceptibleServices();
@@ -704,7 +707,7 @@
             app.mState.setLastTopTime(nowUptime);
             // Simulate the system starting and binding to a service in the app.
             ServiceRecord s = bindService(app, system,
-                    null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+                    null, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
             s.lastTopAlmostPerceptibleBindRequestUptimeMs =
                     nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
             s.getConnections().clear();
@@ -729,7 +732,7 @@
         system.mState.setHasTopUi(true);
         // Simulate the system starting and binding to a service in the app.
         ServiceRecord s = bindService(app, system,
-                null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+                null, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(system, app);
 
@@ -901,7 +904,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        ServiceRecord s = bindService(app, client, null, Context.BIND_WAIVE_PRIORITY,
+        ServiceRecord s = bindService(app, client, null, null, Context.BIND_WAIVE_PRIORITY,
                 mock(IBinder.class));
         s.startRequested = true;
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -921,7 +924,7 @@
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         client.mServices.setTreatLikeActivity(true);
-        bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
+        bindService(app, client, null, null, Context.BIND_WAIVE_PRIORITY
                 | Context.BIND_TREAT_LIKE_ACTIVITY, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -937,7 +940,7 @@
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         IBinder binder = mock(IBinder.class);
-        ServiceRecord s = bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
+        ServiceRecord s = bindService(app, client, null, null, Context.BIND_WAIVE_PRIORITY
                 | Context.BIND_ADJUST_WITH_ACTIVITY | Context.BIND_IMPORTANT, binder);
         ConnectionRecord cr = s.getConnections().get(binder).get(0);
         setFieldValue(ConnectionRecord.class, cr, "activity",
@@ -955,7 +958,7 @@
     public void testUpdateOomAdj_DoOne_Service_Self() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
-        bindService(app, app, null, 0, mock(IBinder.class));
+        bindService(app, app, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app);
 
@@ -970,7 +973,7 @@
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         client.mServices.setTreatLikeActivity(true);
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
 
@@ -988,7 +991,8 @@
         doReturn(true).when(wpc).hasActivities();
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_ALLOW_OOM_MANAGEMENT, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_ALLOW_OOM_MANAGEMENT,
+                mock(IBinder.class));
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1005,7 +1009,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         client.mState.setHasTopUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1023,7 +1027,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_IMPORTANT, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_IMPORTANT, mock(IBinder.class));
         client.mServices.startExecutingService(mock(ServiceRecord.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1039,7 +1043,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1056,7 +1060,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1074,7 +1078,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1090,7 +1094,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1109,7 +1113,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
 
         // In order to trick OomAdjuster to think it has a short-service, we need this logic.
         ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(sService);
@@ -1172,8 +1176,8 @@
         ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
 
-        bindService(app1, pers, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
-        bindService(app2, app1, null, 0, mock(IBinder.class));
+        bindService(app1, pers, null, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+        bindService(app2, app1, null, null, 0, mock(IBinder.class));
 
         updateOomAdj(pers, app1, app2);
 
@@ -1192,7 +1196,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
         BackupRecord backupTarget = new BackupRecord(null, 0, 0, 0);
         backupTarget.app = client;
         doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
@@ -1218,7 +1222,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1233,7 +1237,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_NOT_VISIBLE, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_NOT_VISIBLE, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1248,7 +1252,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         client.mState.setHasOverlayUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1264,7 +1268,7 @@
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
             ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-            bindService(app, client, null,
+            bindService(app, client, null, null,
                     Context.BIND_ALMOST_PERCEPTIBLE | Context.BIND_NOT_FOREGROUND,
                     mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
@@ -1283,7 +1287,7 @@
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
             WindowProcessController wpc = client.getWindowProcessController();
             doReturn(true).when(wpc).isHeavyWeightProcess();
-            bindService(app, client, null,
+            bindService(app, client, null, null,
                     Context.BIND_ALMOST_PERCEPTIBLE | Context.BIND_NOT_FOREGROUND,
                     mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
@@ -1301,7 +1305,7 @@
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
             ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-            bindService(app, client, null,
+            bindService(app, client, null, null,
                     Context.BIND_ALMOST_PERCEPTIBLE,
                     mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
@@ -1320,7 +1324,7 @@
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
             WindowProcessController wpc = client.getWindowProcessController();
             doReturn(true).when(wpc).isHeavyWeightProcess();
-            bindService(app, client, null,
+            bindService(app, client, null, null,
                     Context.BIND_ALMOST_PERCEPTIBLE,
                     mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
@@ -1341,7 +1345,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1356,7 +1360,8 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_IMPORTANT_BACKGROUND, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_IMPORTANT_BACKGROUND,
+                mock(IBinder.class));
         client.mState.setHasOverlayUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, app);
@@ -1496,10 +1501,10 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client2).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1517,10 +1522,10 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app, client2, null, 0, mock(IBinder.class));
+        bindService(app, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, client2, app);
@@ -1537,10 +1542,10 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, client2, app);
@@ -1557,12 +1562,12 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
 
         // Note: We add processes to LRU but still call updateOomAdjLocked() with a specific
         // processes.
@@ -1599,11 +1604,11 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
-        bindService(client, app, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
+        bindService(client, app, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client2, client, null, 0, mock(IBinder.class));
+        bindService(client2, client, null, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2);
@@ -1626,11 +1631,11 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
-        bindService(client2, client, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
+        bindService(client2, client, null, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2);
@@ -1653,18 +1658,18 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
-        bindService(client2, client, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
+        bindService(client2, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
-        bindService(client3, client, null, 0, mock(IBinder.class));
+        bindService(client3, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
-        bindService(client3, client4, null, 0, mock(IBinder.class));
-        bindService(client4, client3, null, 0, mock(IBinder.class));
+        bindService(client3, client4, null, null, 0, mock(IBinder.class));
+        bindService(client4, client3, null, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3, client4);
@@ -1693,16 +1698,16 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
-        bindService(app, client3, null, 0, mock(IBinder.class));
+        bindService(app, client3, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3);
 
@@ -1718,17 +1723,17 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = client2.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
-        bindService(app, client3, null, 0, mock(IBinder.class));
+        bindService(app, client3, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3);
 
@@ -1743,11 +1748,11 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = client2.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
@@ -1755,7 +1760,7 @@
         ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         client4.mState.setForcingToImportant(new Object());
-        bindService(app, client4, null, 0, mock(IBinder.class));
+        bindService(app, client4, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3, client4);
 
@@ -1770,21 +1775,21 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, 0, mock(IBinder.class));
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client, client2, null, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = client2.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
-        bindService(app, client3, null, 0, mock(IBinder.class));
+        bindService(app, client3, null, null, 0, mock(IBinder.class));
         ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         client4.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app, client4, null, 0, mock(IBinder.class));
+        bindService(app, client4, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3, client4);
 
@@ -1802,15 +1807,15 @@
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         WindowProcessController wpc = client.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app, client2, null, 0, mock(IBinder.class));
+        bindService(app, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
-        bindService(app, client3, null, 0, mock(IBinder.class));
+        bindService(app, client3, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(client, client2, client3, app);
 
@@ -1826,7 +1831,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
         bindProvider(client, client2, null, null, false);
@@ -1846,12 +1851,12 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, 0, mock(IBinder.class));
+        bindService(app, client, null, null, 0, mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
         bindProvider(client, client2, null, null, false);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(client2, app, null, 0, mock(IBinder.class));
+        bindService(client2, app, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2);
 
@@ -1912,9 +1917,9 @@
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
         final ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
-        bindService(app1, client1, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+        bindService(app1, client1, null, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                 mock(IBinder.class));
-        bindService(app2, client2, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+        bindService(app2, client2, null, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                 mock(IBinder.class));
         client1.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
@@ -1929,8 +1934,10 @@
         assertBfsl(app1);
         assertBfsl(app2);
 
-        bindService(app1, client1, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
-        bindService(app2, client2, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
+        bindService(app1, client1, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP,
+                mock(IBinder.class));
+        bindService(app2, client2, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP,
+                mock(IBinder.class));
         updateOomAdj(client1, client2, app1, app2);
 
         assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
@@ -1946,8 +1953,8 @@
                 SCHED_GROUP_DEFAULT);
         assertBfsl(app2);
 
-        bindService(client2, app1, null, 0, mock(IBinder.class));
-        bindService(app1, client2, null, 0, mock(IBinder.class));
+        bindService(client2, app1, null, null, 0, mock(IBinder.class));
+        bindService(app1, client2, null, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(false, 0, /* hasNoneType=*/false);
         updateOomAdj(app1, client1, client2);
         assertProcStates(app1, PROCESS_STATE_IMPORTANT_FOREGROUND, VISIBLE_APP_ADJ,
@@ -1968,9 +1975,9 @@
         client1.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         client2.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
 
-        final ServiceRecord s1 = bindService(app1, client1, null,
+        final ServiceRecord s1 = bindService(app1, client1, null, null,
                 Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE, mock(IBinder.class));
-        final ServiceRecord s2 = bindService(app2, client2, null,
+        final ServiceRecord s2 = bindService(app2, client2, null, null,
                 Context.BIND_IMPORTANT, mock(IBinder.class));
 
         updateOomAdj(client1, client2, app1, app2);
@@ -1980,7 +1987,7 @@
         assertProcStates(app2, PROCESS_STATE_PERSISTENT, PERSISTENT_SERVICE_ADJ,
                 SCHED_GROUP_DEFAULT);
 
-        bindService(app2, client1, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+        bindService(app2, client1, null, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
                 mock(IBinder.class));
         updateOomAdj(app2);
         assertProcStates(app2, PROCESS_STATE_PERSISTENT, PERSISTENT_SERVICE_ADJ,
@@ -1995,9 +2002,9 @@
         client1.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         client2.mState.setHasOverlayUi(true);
 
-        bindService(app1, client1, s1, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+        bindService(app1, client1, null, s1, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
                 mock(IBinder.class));
-        bindService(app2, client2, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+        bindService(app2, client2, null, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
                 mock(IBinder.class));
 
         updateOomAdj(client1, client2, app1, app2);
@@ -2030,7 +2037,7 @@
         app1.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
-        bindService(app1, client1, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
+        bindService(app1, client1, null, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
 
         updateOomAdj(client1, app1);
 
@@ -2051,7 +2058,8 @@
         app1.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
-        bindService(app1, client1, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+        bindService(app1, client1, null, null, Context.BIND_ALMOST_PERCEPTIBLE,
+                mock(IBinder.class));
 
         updateOomAdj(client1, app1);
 
@@ -2121,19 +2129,19 @@
 
         final ComponentName cn1 = ComponentName.unflattenFromString(
                 MOCKAPP_PACKAGENAME + "/.TestService");
-        final ServiceRecord s1 = bindService(app1, client1, null, 0, mock(IBinder.class));
+        final ServiceRecord s1 = bindService(app1, client1, null, null, 0, mock(IBinder.class));
         setFieldValue(ServiceRecord.class, s1, "name", cn1);
         s1.startRequested = true;
 
         final ComponentName cn2 = ComponentName.unflattenFromString(
                 MOCKAPP2_PACKAGENAME + "/.TestService");
-        final ServiceRecord s2 = bindService(app2, client2, null, 0, mock(IBinder.class));
+        final ServiceRecord s2 = bindService(app2, client2, null, null, 0, mock(IBinder.class));
         setFieldValue(ServiceRecord.class, s2, "name", cn2);
         s2.startRequested = true;
 
         final ComponentName cn3 = ComponentName.unflattenFromString(
                 MOCKAPP5_PACKAGENAME + "/.TestService");
-        final ServiceRecord s3 = bindService(app3, client1, null, 0, mock(IBinder.class));
+        final ServiceRecord s3 = bindService(app3, client1, null, null, 0, mock(IBinder.class));
         setFieldValue(ServiceRecord.class, s3, "name", cn3);
         s3.startRequested = true;
 
@@ -2177,7 +2185,7 @@
             clientUidRecord.setIdle(true);
             doReturn(ActivityManager.APP_START_MODE_DELAYED).when(sService)
                     .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
-                    anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+                            anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
             doNothing().when(sService.mServices)
                     .scheduleServiceTimeoutLocked(any(ProcessRecord.class));
             updateOomAdj(client1, client2, app1, app2, app3);
@@ -2188,7 +2196,7 @@
         } finally {
             doCallRealMethod().when(sService)
                     .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
-                    anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+                            anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
             sService.mServices.mServiceMap.clear();
             sService.mOomAdjuster.mActiveUids.clear();
         }
@@ -2223,7 +2231,7 @@
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         app2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app, app2, null, 0, mock(IBinder.class));
+        bindService(app, app2, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, app2);
 
@@ -2242,12 +2250,12 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, app2, null, 0, mock(IBinder.class));
+        bindService(app, app2, null, null, 0, mock(IBinder.class));
         ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app2, app3, null, 0, mock(IBinder.class));
+        bindService(app2, app3, null, null, 0, mock(IBinder.class));
         app3.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app3, app, null, 0, mock(IBinder.class));
+        bindService(app3, app, null, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, app2, app3);
 
@@ -2278,21 +2286,21 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        ServiceRecord s = bindService(app, app2, null, null, 0, mock(IBinder.class));
         ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app2, app3, null, 0, mock(IBinder.class));
-        bindService(app3, app, null, 0, mock(IBinder.class));
+        bindService(app2, app3, null, null, 0, mock(IBinder.class));
+        bindService(app3, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = app3.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         app4.mState.setHasOverlayUi(true);
-        bindService(app, app4, s, 0, mock(IBinder.class));
+        bindService(app, app4, null, s, 0, mock(IBinder.class));
         ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app, app5, s, 0, mock(IBinder.class));
+        bindService(app, app5, null, s, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, app2, app3, app4, app5);
 
@@ -2320,21 +2328,21 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        ServiceRecord s = bindService(app, app2, null, null, 0, mock(IBinder.class));
         ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app2, app3, null, 0, mock(IBinder.class));
-        bindService(app3, app, null, 0, mock(IBinder.class));
+        bindService(app2, app3, null, null, 0, mock(IBinder.class));
+        bindService(app3, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = app3.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         app4.mState.setHasOverlayUi(true);
-        bindService(app, app4, s, 0, mock(IBinder.class));
+        bindService(app, app4, null, s, 0, mock(IBinder.class));
         ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app, app5, s, 0, mock(IBinder.class));
+        bindService(app, app5, null, s, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app5, app4, app3, app2, app);
 
@@ -2362,21 +2370,21 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        ServiceRecord s = bindService(app, app2, null, null, 0, mock(IBinder.class));
         ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(app2, app3, null, 0, mock(IBinder.class));
-        bindService(app3, app, null, 0, mock(IBinder.class));
+        bindService(app2, app3, null, null, 0, mock(IBinder.class));
+        bindService(app3, app, null, null, 0, mock(IBinder.class));
         WindowProcessController wpc = app3.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         app4.mState.setHasOverlayUi(true);
-        bindService(app, app4, s, 0, mock(IBinder.class));
+        bindService(app, app4, null, s, 0, mock(IBinder.class));
         ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        bindService(app, app5, s, 0, mock(IBinder.class));
+        bindService(app, app5, null, s, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app3, app4, app2, app, app5);
 
@@ -2404,15 +2412,19 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-        bindService(app, client, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        bindService(app, client, null, null, Context.BIND_INCLUDE_CAPABILITIES,
+                mock(IBinder.class));
         ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
-        bindService(client, client2, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
-        bindService(client2, app, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        bindService(client, client2, null, null, Context.BIND_INCLUDE_CAPABILITIES,
+                mock(IBinder.class));
+        bindService(client2, app, null, null, Context.BIND_INCLUDE_CAPABILITIES,
+                mock(IBinder.class));
         ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
-        bindService(app, client3, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        bindService(app, client3, null, null, Context.BIND_INCLUDE_CAPABILITIES,
+                mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         updateOomAdj(app, client, client2, client3);
 
@@ -2472,10 +2484,10 @@
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         long now = SystemClock.uptimeMillis();
-        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        ServiceRecord s = bindService(app, app2, null, null, 0, mock(IBinder.class));
         s.startRequested = true;
         s.lastActivity = now;
-        s = bindService(app2, app, null, 0, mock(IBinder.class));
+        s = bindService(app2, app, null, null, 0, mock(IBinder.class));
         s.startRequested = true;
         s.lastActivity = now;
         ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
@@ -2507,11 +2519,11 @@
         final int userOwner = 0;
         final int userOther = 1;
         final int cachedAdj1 = sService.mConstants.USE_TIERED_CACHED_ADJ
-                               ? CACHED_APP_MIN_ADJ + 10
-                               : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+                ? CACHED_APP_MIN_ADJ + 10
+                : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
         final int cachedAdj2 = sService.mConstants.USE_TIERED_CACHED_ADJ
-                               ? CACHED_APP_MIN_ADJ + 10
-                               : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+                ? CACHED_APP_MIN_ADJ + 10
+                : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
         doReturn(userOwner).when(sService.mUserController).getCurrentUserId();
 
         final ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
@@ -2626,7 +2638,7 @@
 
         // Simulate binding to a service in the same process using BIND_ABOVE_CLIENT and
         // verify that its OOM adjustment level is unaffected.
-        bindService(app, app, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+        bindService(app, app, null, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
         app.mServices.updateHasAboveClientLocked();
         assertFalse(app.mServices.hasAboveClient());
 
@@ -2644,12 +2656,12 @@
         final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
         long now = SystemClock.uptimeMillis();
-        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        ServiceRecord s = bindService(app, app2, null, null, 0, mock(IBinder.class));
         s.startRequested = true;
         s.lastActivity = now;
-        s = bindService(app2, app3, null, 0, mock(IBinder.class));
+        s = bindService(app2, app3, null, null, 0, mock(IBinder.class));
         s.lastActivity = now;
-        s = bindService(app3, app2, null, 0, mock(IBinder.class));
+        s = bindService(app3, app2, null, null, 0, mock(IBinder.class));
         s.lastActivity = now;
 
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -2678,7 +2690,7 @@
         // Start binding to a service that isn't running yet.
         ServiceRecord sr = makeServiceRecord(app);
         sr.app = null;
-        bindService(null, app, sr, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+        bindService(null, app, null, sr, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
 
         // Since sr.app is null, this service cannot be in the same process as the
         // client so we expect the BIND_ABOVE_CLIENT adjustment to take effect.
@@ -2772,91 +2784,37 @@
                 ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
     }
 
-    private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
-            String packageName, boolean hasShownUi) {
-        long now = SystemClock.uptimeMillis();
-        return makeProcessRecord(sService, pid, uid, processName,
-                packageName, 12345, Build.VERSION_CODES.CUR_DEVELOPMENT,
-                now, now, now, 12345, UNKNOWN_ADJ, UNKNOWN_ADJ,
-                UNKNOWN_ADJ, CACHED_APP_MAX_ADJ,
-                SCHED_GROUP_DEFAULT, SCHED_GROUP_DEFAULT,
-                PROCESS_STATE_NONEXISTENT, PROCESS_STATE_NONEXISTENT,
-                PROCESS_STATE_NONEXISTENT, PROCESS_STATE_NONEXISTENT,
-                0, 0, false, false, false, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE,
-                false, false, false, hasShownUi, false, false, false, false, false, false, null,
-                0, Long.MIN_VALUE, Long.MIN_VALUE, true, 0, null, false);
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoAll_SdkSandbox_attributedClient() {
+        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        ProcessRecord attributedClient = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, true));
+        ProcessRecord sandboxService = spy(new ProcessRecordBuilder(MOCKAPP_PID,
+                MOCKAPP_SDK_SANDBOX_UID, MOCKAPP_SDK_SANDBOX_PROCESSNAME, MOCKAPP_PACKAGENAME)
+                .setSdkSandboxClientAppPackage(MOCKAPP3_PACKAGENAME)
+                .build());
+
+        setProcessesToLru(sandboxService, client, attributedClient);
+
+        client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+        attributedClient.mServices.setHasForegroundServices(true, 0, true);
+        bindService(sandboxService, client, attributedClient, null, 0, mock(IBinder.class));
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        updateOomAdj();
+        assertProcStates(client, PROCESS_STATE_PERSISTENT, PERSISTENT_PROC_ADJ,
+                SCHED_GROUP_DEFAULT);
+        assertProcStates(attributedClient, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                SCHED_GROUP_DEFAULT);
+        assertProcStates(sandboxService, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+                SCHED_GROUP_DEFAULT);
     }
 
-    private ProcessRecord makeProcessRecord(ActivityManagerService service, int pid, int uid,
-            String processName, String packageName, long versionCode, int targetSdkVersion,
-            long lastActivityTime, long lastPssTime, long nextPssTime, long lastPss, int maxAdj,
-            int setRawAdj, int curAdj, int setAdj, int curSchedGroup, int setSchedGroup,
-            int curProcState, int repProcState, int curRawProcState, int setProcState,
-            int connectionGroup, int connectionImportance, boolean serviceb,
-            boolean hasClientActivities, boolean hasForegroundServices, int fgServiceTypes,
-            boolean hasForegroundActivities, boolean repForegroundActivities, boolean systemNoUi,
-            boolean hasShownUi, boolean hasTopUi, boolean hasOverlayUi,
-            boolean runningRemoteAnimation, boolean hasAboveClient, boolean treatLikeActivity,
-            boolean killedByAm, Object forcingToImportant, int numOfCurReceivers,
-            long lastProviderTime, long lastTopTime, boolean cached, int numOfExecutingServices,
-            String isolatedEntryPoint, boolean execServicesFg) {
-        ApplicationInfo ai = spy(new ApplicationInfo());
-        ai.uid = uid;
-        ai.packageName = packageName;
-        ai.longVersionCode = versionCode;
-        ai.targetSdkVersion = targetSdkVersion;
-        ProcessRecord app = new ProcessRecord(service, ai, processName, uid);
-        final ProcessStateRecord state = app.mState;
-        final ProcessServiceRecord services = app.mServices;
-        final ProcessReceiverRecord receivers = app.mReceivers;
-        final ProcessProfileRecord profile = app.mProfile;
-        final ProcessProviderRecord providers = app.mProviders;
-        app.makeActive(mock(IApplicationThread.class), sService.mProcessStats);
-        app.setLastActivityTime(lastActivityTime);
-        app.setKilledByAm(killedByAm);
-        app.setIsolatedEntryPoint(isolatedEntryPoint);
-        setFieldValue(ProcessRecord.class, app, "mWindowProcessController",
-                mock(WindowProcessController.class));
-        profile.setLastPssTime(lastPssTime);
-        profile.setNextPssTime(nextPssTime);
-        profile.setLastPss(lastPss);
-        state.setMaxAdj(maxAdj);
-        state.setSetRawAdj(setRawAdj);
-        state.setCurAdj(curAdj);
-        state.setSetAdj(setAdj);
-        state.setCurrentSchedulingGroup(curSchedGroup);
-        state.setSetSchedGroup(setSchedGroup);
-        state.setCurProcState(curProcState);
-        state.setReportedProcState(repProcState);
-        state.setCurRawProcState(curRawProcState);
-        state.setSetProcState(setProcState);
-        state.setServiceB(serviceb);
-        state.setRepForegroundActivities(repForegroundActivities);
-        state.setHasForegroundActivities(hasForegroundActivities);
-        state.setSystemNoUi(systemNoUi);
-        state.setHasShownUi(hasShownUi);
-        state.setHasTopUi(hasTopUi);
-        state.setRunningRemoteAnimation(runningRemoteAnimation);
-        state.setHasOverlayUi(hasOverlayUi);
-        state.setCached(cached);
-        state.setLastTopTime(lastTopTime);
-        state.setForcingToImportant(forcingToImportant);
-        services.setConnectionGroup(connectionGroup);
-        services.setConnectionImportance(connectionImportance);
-        services.setHasClientActivities(hasClientActivities);
-        services.setHasForegroundServices(hasForegroundServices, fgServiceTypes,
-                /* hasNoneType=*/false);
-        services.setHasAboveClient(hasAboveClient);
-        services.setTreatLikeActivity(treatLikeActivity);
-        services.setExecServicesFg(execServicesFg);
-        for (int i = 0; i < numOfExecutingServices; i++) {
-            services.startExecutingService(mock(ServiceRecord.class));
-        }
-        for (int i = 0; i < numOfCurReceivers; i++) {
-            receivers.addCurReceiver(mock(BroadcastRecord.class));
-        }
-        providers.setLastProviderTime(lastProviderTime);
-        return app;
+    private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
+            String packageName, boolean hasShownUi) {
+        return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(
+                hasShownUi).build();
     }
 
     private ServiceRecord makeServiceRecord(ProcessRecord app) {
@@ -2870,6 +2828,7 @@
         record.appInfo = app.info;
         setFieldValue(ServiceRecord.class, record, "bindings", new ArrayMap<>());
         setFieldValue(ServiceRecord.class, record, "pendingStarts", new ArrayList<>());
+        setFieldValue(ServiceRecord.class, record, "isSdkSandbox", app.isSdkSandbox);
         return record;
     }
 
@@ -2892,11 +2851,11 @@
     }
 
     private ServiceRecord bindService(ProcessRecord service, ProcessRecord client,
-            ServiceRecord record, long bindFlags, IBinder binder) {
+            ProcessRecord attributedClient, ServiceRecord record, long bindFlags, IBinder binder) {
         if (record == null) {
             record = makeServiceRecord(service);
         }
-        AppBindRecord binding = new AppBindRecord(record, null, client, null);
+        AppBindRecord binding = new AppBindRecord(record, null, client, attributedClient);
         ConnectionRecord cr = spy(new ConnectionRecord(binding,
                 mock(ActivityServiceConnectionsHolder.class),
                 mock(IServiceConnection.class), bindFlags,
@@ -2961,4 +2920,140 @@
             assertBfsl(app);
         }
     }
+
+    private static class ProcessRecordBuilder {
+        @SuppressWarnings("UnusedVariable")
+        int mPid;
+        int mUid;
+        String mProcessName;
+        String mPackageName;
+        long mVersionCode = 12345;
+        int mTargetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+        long mLastActivityTime;
+        long mLastPssTime;
+        long mNextPssTime;
+        long mLastPss = 12345;
+        int mMaxAdj = UNKNOWN_ADJ;
+        int mSetRawAdj = UNKNOWN_ADJ;
+        int mCurAdj = UNKNOWN_ADJ;
+        int mSetAdj = CACHED_APP_MAX_ADJ;
+        int mCurSchedGroup = SCHED_GROUP_DEFAULT;
+        int mSetSchedGroup = SCHED_GROUP_DEFAULT;
+        int mCurProcState = PROCESS_STATE_NONEXISTENT;
+        int mRepProcState = PROCESS_STATE_NONEXISTENT;
+        int mCurRawProcState = PROCESS_STATE_NONEXISTENT;
+        int mSetProcState = PROCESS_STATE_NONEXISTENT;
+        int mConnectionGroup = 0;
+        int mConnectionImportance = 0;
+        boolean mServiceb = false;
+        boolean mHasClientActivities = false;
+        boolean mHasForegroundServices = false;
+        int mFgServiceTypes = ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+        boolean mHasForegroundActivities = false;
+        boolean mRepForegroundActivities = false;
+        boolean mSystemNoUi = false;
+        boolean mHasShownUi = false;
+        boolean mHasTopUi = false;
+        boolean mHasOverlayUi = false;
+        boolean mRunningRemoteAnimation = false;
+        boolean mHasAboveClient = false;
+        boolean mTreatLikeActivity = false;
+        boolean mKilledByAm = false;
+        Object mForcingToImportant;
+        int mNumOfCurReceivers = 0;
+        long mLastProviderTime = Long.MIN_VALUE;
+        long mLastTopTime = Long.MIN_VALUE;
+        boolean mCached = true;
+        int mNumOfExecutingServices = 0;
+        String mIsolatedEntryPoint = null;
+        boolean mExecServicesFg = false;
+        String mSdkSandboxClientAppPackage = null;
+
+        ProcessRecordBuilder(int pid, int uid, String processName, String packageName) {
+            mPid = pid;
+            mUid = uid;
+            mProcessName = processName;
+            mPackageName = packageName;
+
+            long now = SystemClock.uptimeMillis();
+            mLastActivityTime = now;
+            mLastPssTime = now;
+            mNextPssTime = now;
+        }
+
+        ProcessRecordBuilder setHasShownUi(boolean hasShownUi) {
+            mHasShownUi = hasShownUi;
+            return this;
+        }
+
+        ProcessRecordBuilder setSdkSandboxClientAppPackage(String sdkSandboxClientAppPackage) {
+            mSdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
+            return this;
+        }
+
+        @SuppressWarnings("GuardedBy")
+        public ProcessRecord build() {
+            ApplicationInfo ai = spy(new ApplicationInfo());
+            ai.uid = mUid;
+            ai.packageName = mPackageName;
+            ai.longVersionCode = mVersionCode;
+            ai.targetSdkVersion = mTargetSdkVersion;
+            doCallRealMethod().when(sService).getPackageManagerInternal();
+            doReturn(null).when(sPackageManagerInternal).getApplicationInfo(
+                    eq(mSdkSandboxClientAppPackage), anyLong(), anyInt(), anyInt());
+            ProcessRecord app = new ProcessRecord(sService, ai, mProcessName, mUid,
+                    mSdkSandboxClientAppPackage, -1, null);
+            final ProcessStateRecord state = app.mState;
+            final ProcessServiceRecord services = app.mServices;
+            final ProcessReceiverRecord receivers = app.mReceivers;
+            final ProcessProfileRecord profile = app.mProfile;
+            final ProcessProviderRecord providers = app.mProviders;
+            app.makeActive(mock(IApplicationThread.class), sService.mProcessStats);
+            app.setLastActivityTime(mLastActivityTime);
+            app.setKilledByAm(mKilledByAm);
+            app.setIsolatedEntryPoint(mIsolatedEntryPoint);
+            setFieldValue(ProcessRecord.class, app, "mWindowProcessController",
+                    mock(WindowProcessController.class));
+            profile.setLastPssTime(mLastPssTime);
+            profile.setNextPssTime(mNextPssTime);
+            profile.setLastPss(mLastPss);
+            state.setMaxAdj(mMaxAdj);
+            state.setSetRawAdj(mSetRawAdj);
+            state.setCurAdj(mCurAdj);
+            state.setSetAdj(mSetAdj);
+            state.setCurrentSchedulingGroup(mCurSchedGroup);
+            state.setSetSchedGroup(mSetSchedGroup);
+            state.setCurProcState(mCurProcState);
+            state.setReportedProcState(mRepProcState);
+            state.setCurRawProcState(mCurRawProcState);
+            state.setSetProcState(mSetProcState);
+            state.setServiceB(mServiceb);
+            state.setRepForegroundActivities(mRepForegroundActivities);
+            state.setHasForegroundActivities(mHasForegroundActivities);
+            state.setSystemNoUi(mSystemNoUi);
+            state.setHasShownUi(mHasShownUi);
+            state.setHasTopUi(mHasTopUi);
+            state.setRunningRemoteAnimation(mRunningRemoteAnimation);
+            state.setHasOverlayUi(mHasOverlayUi);
+            state.setCached(mCached);
+            state.setLastTopTime(mLastTopTime);
+            state.setForcingToImportant(mForcingToImportant);
+            services.setConnectionGroup(mConnectionGroup);
+            services.setConnectionImportance(mConnectionImportance);
+            services.setHasClientActivities(mHasClientActivities);
+            services.setHasForegroundServices(mHasForegroundServices, mFgServiceTypes,
+                    /* hasNoneType=*/false);
+            services.setHasAboveClient(mHasAboveClient);
+            services.setTreatLikeActivity(mTreatLikeActivity);
+            services.setExecServicesFg(mExecServicesFg);
+            for (int i = 0; i < mNumOfExecutingServices; i++) {
+                services.startExecutingService(mock(ServiceRecord.class));
+            }
+            for (int i = 0; i < mNumOfCurReceivers; i++) {
+                receivers.addCurReceiver(mock(BroadcastRecord.class));
+            }
+            providers.setLastProviderTime(mLastProviderTime);
+            return app;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java b/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java
new file mode 100644
index 0000000..08a6529
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java
@@ -0,0 +1,333 @@
+/*
+ * 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.adaptiveauth;
+
+import static android.adaptiveauth.Flags.FLAG_ENABLE_ADAPTIVE_AUTH;
+import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
+import static android.security.Flags.FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS;
+
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
+import static com.android.server.adaptiveauth.AdaptiveAuthService.MAX_ALLOWED_FAILED_AUTH_ATTEMPTS;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.hardware.biometrics.AuthenticationStateListener;
+import android.hardware.biometrics.BiometricManager;
+import android.os.RemoteException;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockSettingsStateListener;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+import com.android.server.wm.WindowManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * atest FrameworksServicesTests:AdaptiveAuthServiceTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AdaptiveAuthServiceTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    private static final int PRIMARY_USER_ID = 0;
+    private static final int MANAGED_PROFILE_USER_ID = 12;
+    private static final int DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS = 0;
+    private static final int REASON_UNKNOWN = 0; // BiometricRequestConstants.RequestReason
+
+    private Context mContext;
+    private AdaptiveAuthService mAdaptiveAuthService;
+
+    @Mock
+    LockPatternUtils mLockPatternUtils;
+    @Mock
+    private LockSettingsInternal mLockSettings;
+    @Mock
+    private BiometricManager mBiometricManager;
+    @Mock
+    private KeyguardManager mKeyguardManager;
+    @Mock
+    private WindowManagerInternal mWindowManager;
+    @Mock
+    private UserManagerInternal mUserManager;
+
+    @Captor
+    ArgumentCaptor<LockSettingsStateListener> mLockSettingsStateListenerCaptor;
+    @Captor
+    ArgumentCaptor<AuthenticationStateListener> mAuthenticationStateListenerCaptor;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mSetFlagsRule.enableFlags(FLAG_ENABLE_ADAPTIVE_AUTH);
+        mSetFlagsRule.enableFlags(FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS);
+        mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
+        when(mContext.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager);
+
+        LocalServices.removeServiceForTest(LockSettingsInternal.class);
+        LocalServices.addService(LockSettingsInternal.class, mLockSettings);
+        LocalServices.removeServiceForTest(WindowManagerInternal.class);
+        LocalServices.addService(WindowManagerInternal.class, mWindowManager);
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, mUserManager);
+
+        mAdaptiveAuthService = new AdaptiveAuthService(mContext, mLockPatternUtils);
+        mAdaptiveAuthService.init();
+
+        verify(mLockSettings).registerLockSettingsStateListener(
+                mLockSettingsStateListenerCaptor.capture());
+        verify(mBiometricManager).registerAuthenticationStateListener(
+                mAuthenticationStateListenerCaptor.capture());
+
+        // Set PRIMARY_USER_ID as the parent of MANAGED_PROFILE_USER_ID
+        when(mUserManager.getProfileParentId(eq(MANAGED_PROFILE_USER_ID)))
+                .thenReturn(PRIMARY_USER_ID);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(LockSettingsInternal.class);
+        LocalServices.removeServiceForTest(WindowManagerInternal.class);
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthSucceeded()
+            throws RemoteException {
+        mLockSettingsStateListenerCaptor.getValue().onAuthenticationSucceeded(PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthFailed_once()
+            throws RemoteException {
+        mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(1 /* expectedCntFailedAttempts */, PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthFailed_multiple_deviceCurrentlyLocked()
+            throws RemoteException {
+        // Device is currently locked and Keyguard is showing
+        when(mKeyguardManager.isDeviceLocked(PRIMARY_USER_ID)).thenReturn(true);
+        when(mKeyguardManager.isKeyguardLocked()).thenReturn(true);
+
+        for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
+            mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(MAX_ALLOWED_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthFailed_multiple_deviceCurrentlyNotLocked()
+            throws RemoteException {
+        // Device is currently not locked and Keyguard is not showing
+        when(mKeyguardManager.isDeviceLocked(PRIMARY_USER_ID)).thenReturn(false);
+        when(mKeyguardManager.isKeyguardLocked()).thenReturn(false);
+
+        for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
+            mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyLockDevice(PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_biometricAuthSucceeded()
+            throws RemoteException {
+        mAuthenticationStateListenerCaptor.getValue()
+                .onAuthenticationSucceeded(REASON_UNKNOWN, PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_biometricAuthFailed_once()
+            throws RemoteException {
+        mAuthenticationStateListenerCaptor.getValue()
+                .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(1 /* expectedCntFailedAttempts */, PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_biometricAuthFailed_multiple_deviceCurrentlyLocked()
+            throws RemoteException {
+        // Device is currently locked and Keyguard is showing
+        when(mKeyguardManager.isDeviceLocked(PRIMARY_USER_ID)).thenReturn(true);
+        when(mKeyguardManager.isKeyguardLocked()).thenReturn(true);
+
+        for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
+            mAuthenticationStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(MAX_ALLOWED_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_biometricAuthFailed_multiple_deviceCurrentlyNotLocked()
+            throws RemoteException {
+        // Device is currently not locked and Keyguard is not showing
+        when(mKeyguardManager.isDeviceLocked(PRIMARY_USER_ID)).thenReturn(false);
+        when(mKeyguardManager.isKeyguardLocked()).thenReturn(false);
+
+        for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
+            mAuthenticationStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyLockDevice(PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_biometricAuthFailedThenPrimaryAuthSucceeded()
+            throws RemoteException {
+        // Three failed biometric auth attempts
+        for (int i = 0; i < 3; i++) {
+            mAuthenticationStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        }
+        // One successful primary auth attempt
+        mLockSettingsStateListenerCaptor.getValue().onAuthenticationSucceeded(PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthFailedThenBiometricAuthSucceeded()
+            throws RemoteException {
+        // Three failed primary auth attempts
+        for (int i = 0; i < 3; i++) {
+            mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
+        }
+        // One successful biometric auth attempt
+        mAuthenticationStateListenerCaptor.getValue()
+                .onAuthenticationSucceeded(REASON_UNKNOWN, PRIMARY_USER_ID);
+        waitForAuthCompletion();
+
+        verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
+                PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_primaryUser()
+            throws RemoteException {
+        // Three failed primary auth attempts
+        for (int i = 0; i < 3; i++) {
+            mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
+        }
+        // Two failed biometric auth attempts
+        for (int i = 0; i < 2; i++) {
+            mAuthenticationStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyLockDevice(PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profileOfPrimaryUser()
+            throws RemoteException {
+        // Three failed primary auth attempts
+        for (int i = 0; i < 3; i++) {
+            mLockSettingsStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(MANAGED_PROFILE_USER_ID);
+        }
+        // Two failed biometric auth attempts
+        for (int i = 0; i < 2; i++) {
+            mAuthenticationStateListenerCaptor.getValue()
+                    .onAuthenticationFailed(REASON_UNKNOWN, MANAGED_PROFILE_USER_ID);
+        }
+        waitForAuthCompletion();
+
+        verifyLockDevice(MANAGED_PROFILE_USER_ID);
+    }
+
+    private void verifyNotLockDevice(int expectedCntFailedAttempts, int userId) {
+        assertEquals(expectedCntFailedAttempts,
+                mAdaptiveAuthService.mFailedAttemptsForUser.get(userId));
+        verify(mWindowManager, never()).lockNow();
+    }
+
+    private void verifyLockDevice(int userId) {
+        assertEquals(MAX_ALLOWED_FAILED_AUTH_ATTEMPTS,
+                mAdaptiveAuthService.mFailedAttemptsForUser.get(userId));
+        verify(mLockPatternUtils).requireStrongAuth(
+                eq(SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST), eq(userId));
+        // If userId is MANAGED_PROFILE_USER_ID, the StrongAuthFlag of its parent (PRIMARY_USER_ID)
+        // should also be verified
+        if (userId == MANAGED_PROFILE_USER_ID) {
+            verify(mLockPatternUtils).requireStrongAuth(
+                    eq(SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST), eq(PRIMARY_USER_ID));
+        }
+        verify(mWindowManager).lockNow();
+    }
+
+    /**
+     * Wait for all auth events to complete before verification
+     */
+    private static void waitForAuthCompletion() {
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/adaptiveauth/OWNERS b/services/tests/servicestests/src/com/android/server/adaptiveauth/OWNERS
new file mode 100644
index 0000000..0218a78
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/adaptiveauth/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/adaptiveauth/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index aefa6de..abd3abe 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -75,12 +75,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.internal.util.test.LocalServiceKeeperRule;
+import com.android.server.LocalServices;
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.wm.WindowManagerInternal;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -164,17 +164,15 @@
     @Captor
     private ArgumentCaptor<ContentRecordingSession> mSessionCaptor;
 
-    @Rule
-    public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();
-
     @Before
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mWatcherCallback.asBinder()).thenReturn(new Binder());
 
-        mLocalServiceKeeperRule.overrideLocalService(ActivityManagerInternal.class, mAmInternal);
-        mLocalServiceKeeperRule.overrideLocalService(WindowManagerInternal.class,
-                mWindowManagerInternal);
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.addService(ActivityManagerInternal.class, mAmInternal);
+        LocalServices.removeServiceForTest(WindowManagerInternal.class);
+        LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
 
         mContext = spy(new ContextWrapper(
                 InstrumentationRegistry.getInstrumentation().getTargetContext()));
@@ -189,6 +187,12 @@
         mService = new MediaProjectionManagerService(mContext);
     }
 
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.removeServiceForTest(WindowManagerInternal.class);
+    }
+
     @Test
     public void testGetActiveProjectionInfoInternal() throws NameNotFoundException {
         assertThat(mService.getActiveProjectionInfo()).isNull();
@@ -384,16 +388,16 @@
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(
                 service);
         // No starts yet, and not timed out yet - so still valid.
-        assertThat(projection.isValidInternal()).isTrue();
+        assertThat(projection.isValid()).isTrue();
 
         // Only one start - so still valid.
         projection.start(mIMediaProjectionCallback);
-        assertThat(projection.isValidInternal()).isTrue();
+        assertThat(projection.isValid()).isTrue();
 
         // Second start - technically allowed to start again, without stopping in between.
         // Token should no longer be valid.
         projection.start(mIMediaProjectionCallback);
-        assertThat(projection.isValidInternal()).isFalse();
+        assertThat(projection.isValid()).isFalse();
     }
 
     @Test
@@ -403,17 +407,17 @@
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(
                 service);
         // No starts yet, and not timed out yet - so still valid.
-        assertThat(projection.isValidInternal()).isTrue();
+        assertThat(projection.isValid()).isTrue();
 
         // Only one start - so still valid.
         projection.start(mIMediaProjectionCallback);
-        assertThat(projection.isValidInternal()).isTrue();
+        assertThat(projection.isValid()).isTrue();
 
         projection.stop();
 
         // Second start - so not valid.
         projection.start(mIMediaProjectionCallback);
-        assertThat(projection.isValidInternal()).isFalse();
+        assertThat(projection.isValid()).isFalse();
     }
 
     @Test
@@ -438,7 +442,7 @@
         mClock.fastForward(projection.mDefaultTimeoutMs + 10);
 
         // Immediate timeout - so no longer valid.
-        assertThat(projection.isValidInternal()).isFalse();
+        assertThat(projection.isValid()).isFalse();
     }
 
     @Test
@@ -448,10 +452,10 @@
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(
                 service);
         // Simulate MediaProjection#createVirtualDisplay being invoked previously.
-        projection.notifyVirtualDisplayCreatedInternal(10);
+        projection.notifyVirtualDisplayCreated(10);
 
         // Trying to re-use token on another MediaProjection#createVirtualDisplay - no longer valid.
-        assertThat(projection.isValidInternal()).isFalse();
+        assertThat(projection.isValid()).isFalse();
     }
 
     // TODO(269273190): Test flag using compat annotations instead.
@@ -467,7 +471,7 @@
         // Second start - so not valid.
         projection.start(mIMediaProjectionCallback);
 
-        assertThrows(SecurityException.class, projection::isValidInternal);
+        assertThrows(SecurityException.class, projection::isValid);
     }
 
     // TODO(269273190): Test flag using compat annotations instead.
@@ -484,7 +488,7 @@
         // Second start - so not valid.
         projection.start(mIMediaProjectionCallback);
 
-        assertThat(projection.isValidInternal()).isFalse();
+        assertThat(projection.isValid()).isFalse();
     }
 
     @Test
@@ -623,7 +627,7 @@
         mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, projection);
 
         // Virtual Display is finally created.
-        projection.notifyVirtualDisplayCreatedInternal(10);
+        projection.notifyVirtualDisplayCreated(10);
         verifySetSessionWithContent(ContentRecordingSession.RECORD_CONTENT_DISPLAY);
     }
 
@@ -726,7 +730,7 @@
             throws Exception {
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
         projection.start(mIMediaProjectionCallback);
-        projection.notifyVirtualDisplayCreatedInternal(10);
+        projection.notifyVirtualDisplayCreated(10);
         // Waiting for user to review consent.
         assertThat(mService.isCurrentProjection(projection)).isTrue();
         doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
@@ -781,9 +785,9 @@
             @RecordContent int recordedContent)
             throws NameNotFoundException {
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
-        projection.setLaunchCookieInternal(new LaunchCookie());
+        projection.setLaunchCookie(new LaunchCookie());
         projection.start(mIMediaProjectionCallback);
-        projection.notifyVirtualDisplayCreatedInternal(10);
+        projection.notifyVirtualDisplayCreated(10);
         // Waiting for user to review consent.
         doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
                 any(ContentRecordingSession.class));
@@ -804,7 +808,7 @@
             throws NameNotFoundException {
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
         projection.start(mIMediaProjectionCallback);
-        projection.notifyVirtualDisplayCreatedInternal(10);
+        projection.notifyVirtualDisplayCreated(10);
         // Waiting for user to review consent.
         doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
                 eq(mWaitingDisplaySession));
@@ -822,7 +826,7 @@
     public void testSetUserReviewGrantedConsentResult_displayMirroring_noPriorSession()
             throws NameNotFoundException {
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
-        projection.setLaunchCookieInternal(new LaunchCookie());
+        projection.setLaunchCookie(new LaunchCookie());
         projection.start(mIMediaProjectionCallback);
         // Skip setting the prior session details.
 
@@ -841,7 +845,7 @@
     public void testSetUserReviewGrantedConsentResult_displayMirroring_sessionNotWaiting()
             throws NameNotFoundException {
         MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
-        projection.setLaunchCookieInternal(new LaunchCookie());
+        projection.setLaunchCookie(new LaunchCookie());
         projection.start(mIMediaProjectionCallback);
         // Session is not waiting for user's consent.
         doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 847c9d0..d5eeaa7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1561,7 +1561,7 @@
                 .build();
 
         final int result = starter.recycleTask(task, null, null, null,
-                BalVerdict.ALLOW_BY_DEFAULT);
+                BalVerdict.ALLOW_PRIVILEGED);
         assertThat(result == START_SUCCESS).isTrue();
         assertThat(starter.mAddingToTask).isTrue();
     }
@@ -2075,7 +2075,7 @@
         starter.startActivityInner(target, source, null /* voiceSession */,
                 null /* voiceInteractor */, 0 /* startFlags */,
                 options, inTask, inTaskFragment,
-                BalVerdict.ALLOW_BY_DEFAULT,
+                BalVerdict.ALLOW_PRIVILEGED,
                 null /* intentGrants */, -1 /* realCallingUid */);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 60dfe6f..887e5ee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -811,7 +811,7 @@
 
     @Test
     public void testDisplayContentUpdatesRecording_withSurface() {
-        createContentRecorder(createDefaultDisplayInfo());
+        defaultInit();
         // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
         // mirror.
         setUpDefaultTaskDisplayAreaWindowToken();
@@ -820,7 +820,6 @@
         // getDisplaySurfaceDefaultSize (done by surfaceControlMirrors in setUp).
         final DisplayContent virtualDisplay =
                 mRootWindowContainer.getDisplayContent(mDisplaySession.getVirtualDisplayId());
-        virtualDisplay.setContentRecorder(mContentRecorder);
         mWm.mContentRecordingController.setContentRecordingSessionLocked(mDisplaySession, mWm);
         virtualDisplay.updateRecording();
 
@@ -845,7 +844,6 @@
         // WHEN getting the DisplayContent for the new virtual display.
         final DisplayContent virtualDisplay =
                 mRootWindowContainer.getDisplayContent(mDisplaySession.getVirtualDisplayId());
-        virtualDisplay.setContentRecorder(mContentRecorder);
         // Return the default display as the value to mirror to ensure the VD with flag mirroring
         // creates a ContentRecordingSession automatically.
         doReturn(DEFAULT_DISPLAY).when(mWm.mDisplayManagerInternal).getDisplayIdToMirror(anyInt());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecordingControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecordingControllerTests.java
index 42004c3..c84fe08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecordingControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecordingControllerTests.java
@@ -24,7 +24,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 
 import android.platform.test.annotations.Presubmit;
@@ -32,8 +31,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.wm.ContentRecorder.MediaProjectionManagerWrapper;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,11 +68,6 @@
         mVirtualDisplayId = mVirtualDisplayContent.getDisplayId();
         mWm.mRoot.onDisplayAdded(mVirtualDisplayId);
         spyOn(mVirtualDisplayContent);
-        final MediaProjectionManagerWrapper
-                mediaProjectionManagerWrapper = mock(MediaProjectionManagerWrapper.class);
-        final ContentRecorder contentRecorder = new ContentRecorder(mVirtualDisplayContent,
-                mediaProjectionManagerWrapper, /* correctForAnisotropicPixels= */ false);
-        mVirtualDisplayContent.setContentRecorder(contentRecorder);
 
         mDefaultSession.setVirtualDisplayId(mVirtualDisplayId);
         mWaitingDisplaySession.setVirtualDisplayId(mVirtualDisplayId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index c404c77..bb5887d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -187,7 +187,7 @@
                 /* options */null,
                 /* inTask */null,
                 /* inTaskFragment */ null,
-                BalVerdict.ALLOW_BY_DEFAULT,
+                BalVerdict.ALLOW_PRIVILEGED,
                 /* intentGrants */null,
                 /* realCaiingUid */ -1);
 
@@ -217,7 +217,7 @@
                 /* options= */null,
                 /* inTask= */null,
                 /* inTaskFragment= */ null,
-                BalVerdict.ALLOW_BY_DEFAULT,
+                BalVerdict.ALLOW_PRIVILEGED,
                 /* intentGrants= */null,
                 /* realCaiingUid */ -1);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8b0fc2c..cd3ce91 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -1424,6 +1424,25 @@
         assertFalse(window2.isSecureLocked());
     }
 
+    @Test
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
+    public void testIsSecureLocked_sensitiveContentBlockOrClearScreenCaptureForApp() {
+        String testPackage = "test";
+        int ownerId = 20;
+        final WindowState window = createWindow(null, TYPE_APPLICATION, "window", ownerId);
+        window.mAttrs.packageName = testPackage;
+        assertFalse(window.isSecureLocked());
+
+        PackageInfo blockedPackage = new PackageInfo(testPackage, ownerId);
+        ArraySet<PackageInfo> blockedPackages = new ArraySet();
+        blockedPackages.add(blockedPackage);
+        mWm.mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedPackages);
+        assertTrue(window.isSecureLocked());
+
+        mWm.mSensitiveContentPackages.removeBlockScreenCaptureForApps(blockedPackages);
+        assertFalse(window.isSecureLocked());
+    }
+
     private static class TestImeTargetChangeListener implements ImeTargetChangeListener {
         private IBinder mImeTargetToken;
         private boolean mIsRemoved;
diff --git a/telecomm/java/android/telecom/CallAttributes.java b/telecomm/java/android/telecom/CallAttributes.java
index 8c6e101..afd34fc 100644
--- a/telecomm/java/android/telecom/CallAttributes.java
+++ b/telecomm/java/android/telecom/CallAttributes.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -24,6 +25,8 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import com.android.server.telecom.flags.Flags;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
@@ -113,7 +116,8 @@
     public static final int VIDEO_CALL = 2;
 
     /** @hide */
-    @IntDef(value = {SUPPORTS_SET_INACTIVE, SUPPORTS_STREAM, SUPPORTS_TRANSFER}, flag = true)
+    @IntDef(value = {SUPPORTS_SET_INACTIVE, SUPPORTS_STREAM, SUPPORTS_TRANSFER,
+            SUPPORTS_VIDEO_CALLING}, flag = true)
     @Retention(RetentionPolicy.SOURCE)
     public @interface CallCapability {
     }
@@ -133,6 +137,12 @@
      * The call can be completely transferred from one endpoint to another.
      */
     public static final int SUPPORTS_TRANSFER = 1 << 3;
+    /**
+     * The call supports video calling. This allows clients to gate video calling on a per call
+     * basis as opposed to re-registering the phone account.
+     */
+    @FlaggedApi(Flags.FLAG_TRANSACTIONAL_VIDEO_STATE)
+    public static final int SUPPORTS_VIDEO_CALLING = 1 << 4;
 
     /**
      * Build an instance of {@link CallAttributes}. In order to build a valid instance, a
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index a1407869..808a575 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -293,12 +293,50 @@
         try {
             mServerInterface.setMuteState(isMuted,
                     new CallControlResultReceiver("requestMuteState", executor, callback));
-
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
     }
 
+     /**
+     * Request a new video state for the ongoing call. This can only be changed if the application
+     * has registered a {@link PhoneAccount} with the
+     * {@link PhoneAccount#CAPABILITY_SUPPORTS_VIDEO_CALLING} and set the
+     * {@link CallAttributes#SUPPORTS_VIDEO_CALLING} when adding the call via
+     * {@link TelecomManager#addCall(CallAttributes, Executor, OutcomeReceiver,
+     *                                                      CallControlCallback, CallEventCallback)}
+     *
+     * @param videoState to report to Telecom. To see the valid argument to pass,
+      *                   see {@link CallAttributes.CallType}.
+     * @param executor   The {@link Executor} on which the {@link OutcomeReceiver} callback
+     *                   will be called on.
+     * @param callback   that will be completed on the Telecom side that details success or failure
+     *                   of the requested operation.
+     *
+     *                   {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
+     *                   switched the video state.
+     *
+     *                   {@link OutcomeReceiver#onError} will be called if Telecom has failed to set
+     *                   the new video state.  A {@link CallException} will be passed
+     *                   that details why the operation failed.
+     * @throws IllegalArgumentException if the argument passed for videoState is invalid.  To see a
+     * list of valid states, see {@link CallAttributes.CallType}.
+     */
+     @FlaggedApi(Flags.FLAG_TRANSACTIONAL_VIDEO_STATE)
+     public void requestVideoState(@CallAttributes.CallType int videoState,
+             @CallbackExecutor @NonNull Executor executor,
+             @NonNull OutcomeReceiver<Void, CallException> callback) {
+         validateVideoState(videoState);
+         Objects.requireNonNull(executor);
+         Objects.requireNonNull(callback);
+         try {
+             mServerInterface.requestVideoState(videoState, mCallId,
+                     new CallControlResultReceiver("requestVideoState", executor, callback));
+         } catch (RemoteException e) {
+             throw e.rethrowAsRuntimeException();
+         }
+     }
+
     /**
      * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
      * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index a41c011..b0438bf 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -16,9 +16,12 @@
 
 package android.telecom;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.os.Bundle;
 
+import com.android.server.telecom.flags.Flags;
+
 import java.util.List;
 
 /**
@@ -51,6 +54,14 @@
     void onMuteStateChanged(boolean isMuted);
 
     /**
+     * Called when the video state changes.
+     *
+     * @param videoState The current video state.
+     */
+    @FlaggedApi(Flags.FLAG_TRANSACTIONAL_VIDEO_STATE)
+    default void onVideoStateChanged(@CallAttributes.CallType int videoState) {}
+
+    /**
      * Telecom is informing the client user requested call streaming but the stream can't be
      * started.
      *
diff --git a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
index 467e89c..a2c6086 100644
--- a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
+++ b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
@@ -33,6 +33,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.server.telecom.flags.Flags;
+
 import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -148,6 +150,7 @@
         private static final String ON_REQ_ENDPOINT_CHANGE = "onRequestEndpointChange";
         private static final String ON_AVAILABLE_CALL_ENDPOINTS = "onAvailableCallEndpointsChanged";
         private static final String ON_MUTE_STATE_CHANGED = "onMuteStateChanged";
+        private static final String ON_VIDEO_STATE_CHANGED = "onVideoStateChanged";
         private static final String ON_CALL_STREAMING_FAILED = "onCallStreamingFailed";
         private static final String ON_EVENT = "onEvent";
 
@@ -261,6 +264,11 @@
             handleEventCallback(callId, ON_MUTE_STATE_CHANGED, isMuted);
         }
 
+        @Override
+        public void onVideoStateChanged(String callId, int videoState) {
+            handleEventCallback(callId, ON_VIDEO_STATE_CHANGED, videoState);
+        }
+
         public void handleEventCallback(String callId, String action, Object arg) {
             Log.d(TAG, TextUtils.formatSimple("hEC: [%s], callId=[%s]", action, callId));
             // lookup the callEventCallback associated with the particular call
@@ -281,6 +289,11 @@
                             case ON_MUTE_STATE_CHANGED:
                                 callback.onMuteStateChanged((boolean) arg);
                                 break;
+                            case ON_VIDEO_STATE_CHANGED:
+                                if (Flags.transactionalVideoState()) {
+                                    callback.onVideoStateChanged((int) arg);
+                                }
+                                break;
                             case ON_CALL_STREAMING_FAILED:
                                 callback.onCallStreamingFailed((int) arg /* reason */);
                                 break;
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index 372e4a12..ac49660 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -34,4 +34,5 @@
     void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
     void setMuteState(boolean isMuted, in ResultReceiver callback);
     void sendEvent(String callId, String event, in Bundle extras);
+    void requestVideoState(int videoState, String callId, in ResultReceiver callback);
 }
\ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
index 213cafb..e4d6b0c 100644
--- a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
@@ -45,6 +45,8 @@
     void onCallEndpointChanged(String callId, in CallEndpoint endpoint);
     void onAvailableCallEndpointsChanged(String callId, in List<CallEndpoint> endpoint);
     void onMuteStateChanged(String callId, boolean isMuted);
+    // -- Video Related
+    void onVideoStateChanged(String callId, int videoState);
     // -- Events
     void onEvent(String callId, String event, in Bundle extras);
     // hidden methods that help with cleanup
diff --git a/telephony/java/android/telephony/DomainSelectionService.java b/telephony/java/android/telephony/DomainSelectionService.java
index 4ff9712..633694a 100644
--- a/telephony/java/android/telephony/DomainSelectionService.java
+++ b/telephony/java/android/telephony/DomainSelectionService.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -855,7 +856,8 @@
      *
      * @return an {@link Executor} used to execute methods called remotely by the framework.
      */
-    public @NonNull Executor onCreateExecutor() {
+    @SuppressLint("OnNameExpected")
+    public @NonNull Executor getCreateExecutor() {
         return Runnable::run;
     }
 
@@ -869,7 +871,7 @@
     public final @NonNull Executor getCachedExecutor() {
         synchronized (mExecutorLock) {
             if (mExecutor == null) {
-                Executor e = onCreateExecutor();
+                Executor e = getCreateExecutor();
                 mExecutor = (e != null) ? e : Runnable::run;
             }
             return mExecutor;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 041822b..fd9aae9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -15011,6 +15011,27 @@
     }
 
     /**
+     * Get the emergency assistance package name.
+     *
+     * @return the package name of the emergency assistance app.
+     * @throws IllegalStateException if emergency assistance is not enabled.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @FlaggedApi(android.permission.flags.Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED)
+    @NonNull
+    @SystemApi
+    public String getEmergencyAssistancePackage() {
+        if (!isEmergencyAssistanceEnabled()) {
+            throw new IllegalStateException("isEmergencyAssistanceEnabled() is false.");
+        }
+        String emergencyRole = mContext.getSystemService(RoleManager.class)
+                .getEmergencyRoleHolder(mContext.getUserId());
+        return Objects.requireNonNull(emergencyRole, "Emergency role holder must not be null");
+    }
+
+    /**
      * Get the emergency number list based on current locale, sim, default, modem and network.
      *
      * <p>In each returned list, the emergency number {@link EmergencyNumber} coming from higher
diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh
deleted file mode 100755
index a6847ae..0000000
--- a/tools/hoststubgen/scripts/run-all-tests.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2023 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.
-
-source "${0%/*}"/../common.sh
-
-# Move to the top directory of hoststubgen
-cd ..
-
-ATEST_ARGS="--host"
-
-# These tests are known to pass.
-READY_TEST_MODULES=(
-  hoststubgen-test-tiny-test
-  CtsUtilTestCasesRavenwood
-  CtsOsTestCasesRavenwood # This one uses native sustitution, so let's run it too.
-)
-
-MUST_BUILD_MODULES=(
-    "${NOT_READY_TEST_MODULES[*]}"
-)
-
-# First, build all the test / etc modules. This shouldn't fail.
-run m "${MUST_BUILD_MODULES[@]}"
-
-# Run the hoststubgen unittests / etc
-run atest $ATEST_ARGS hoststubgentest hoststubgen-invoke-test
-
-# Next, run the golden check. This should always pass too.
-# The following scripts _should_ pass too, but they depend on the internal paths to soong generated
-# files, and they may fail when something changes in the build system.
-run ./hoststubgen/test-tiny-framework/diff-and-update-golden.sh
-
-run ./hoststubgen/test-tiny-framework/run-test-manually.sh
-run atest $ATEST_ARGS tiny-framework-dump-test
-
-# This script is already broken on goog/master
-# run ./scripts/build-framework-hostside-jars-without-genrules.sh
-
-# These tests should all pass.
-run atest $ATEST_ARGS ${READY_TEST_MODULES[*]}
-
-echo ""${0##*/}" finished, with no failures. Ready to submit!"