Merge "Add training data egress flag for Hotword Detection Service" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 931e97e..c30164c 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -21,6 +21,7 @@
     ":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
     ":android.security.flags-aconfig-java{.generated_srcjars}",
     ":android.view.flags-aconfig-java{.generated_srcjars}",
+    ":android.view.accessibility.flags-aconfig-java{.generated_srcjars}",
     ":camera_platform_flags_core_java_lib{.generated_srcjars}",
     ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
     ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
@@ -241,6 +242,24 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// View.accessibility
+aconfig_declarations {
+    name: "android.view.accessibility.flags-aconfig",
+    package: "android.view.accessibility",
+    srcs: ["core/java/android/view/accessibility/flags/*.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.view.accessibility.flags-aconfig-java",
+    aconfig_declarations: "android.view.accessibility.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+cc_aconfig_library {
+    name: "aconfig_view_accessibility_flags_c_lib",
+    aconfig_declarations: "android.view.accessibility.flags-aconfig",
+}
+
 // Widget
 aconfig_declarations {
     name: "android.widget.flags-aconfig",
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index fbcaa52..6461c00 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -209,6 +209,7 @@
     custom_template: "droiddoc-templates-sdk",
     resourcesdir: "docs/html/reference/images/",
     resourcesoutdir: "reference/android/images/",
+    lint_baseline: "javadoc-lint-baseline",
     hdf: [
         "dac true",
         "sdk.codename O",
diff --git a/api/api.go b/api/api.go
index 83804c6..8df6dab 100644
--- a/api/api.go
+++ b/api/api.go
@@ -115,6 +115,7 @@
 }
 
 type Bazel_module struct {
+	Label              *string
 	Bp2build_available *bool
 }
 type bazelProperties struct {
@@ -141,6 +142,8 @@
 	ModuleTag string
 	// public, system, module-lib or system-server
 	Scope string
+	// True if there is a bp2build definition for this module
+	Bp2buildDefined bool
 }
 
 func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) {
@@ -153,8 +156,10 @@
 	if txt.Scope != "public" {
 		filename = txt.Scope + "-" + filename
 	}
+	moduleName := ctx.ModuleName() + "-" + filename
+
 	props := genruleProps{}
-	props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
+	props.Name = proptools.StringPtr(moduleName)
 	props.Tools = []string{"metalava"}
 	props.Out = []string{filename}
 	props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)")
@@ -172,7 +177,20 @@
 		},
 	}
 	props.Visibility = []string{"//visibility:public"}
-	ctx.CreateModule(genrule.GenRuleFactory, &props, &bp2buildNotAvailable)
+	bazelProps := bazelProperties{
+		&Bazel_module{
+			Bp2build_available: proptools.BoolPtr(false),
+		},
+	}
+	if txt.Bp2buildDefined {
+		moduleDir := ctx.ModuleDir()
+		if moduleDir == android.Bp2BuildTopLevel {
+			moduleDir = ""
+		}
+		label := fmt.Sprintf("//%s:%s", moduleDir, moduleName)
+		bazelProps.Label = &label
+	}
+	ctx.CreateModule(genrule.GenRuleFactory, &props, &bazelProps)
 }
 
 func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
@@ -304,38 +322,43 @@
 
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
 	distFilename := []string{"android.txt", "android-removed.txt"}
+	bp2BuildDefined := []bool{true, false}
 	for i, f := range []string{"current.txt", "removed.txt"} {
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:  f,
-			DistFilename: distFilename[i],
-			BaseTxt:      ":non-updatable-" + f,
-			Modules:      bootclasspath,
-			ModuleTag:    "{.public" + tagSuffix[i],
-			Scope:        "public",
+			TxtFilename:     f,
+			DistFilename:    distFilename[i],
+			BaseTxt:         ":non-updatable-" + f,
+			Modules:         bootclasspath,
+			ModuleTag:       "{.public" + tagSuffix[i],
+			Scope:           "public",
+			Bp2buildDefined: bp2BuildDefined[i],
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:  f,
-			DistFilename: distFilename[i],
-			BaseTxt:      ":non-updatable-system-" + f,
-			Modules:      bootclasspath,
-			ModuleTag:    "{.system" + tagSuffix[i],
-			Scope:        "system",
+			TxtFilename:     f,
+			DistFilename:    distFilename[i],
+			BaseTxt:         ":non-updatable-system-" + f,
+			Modules:         bootclasspath,
+			ModuleTag:       "{.system" + tagSuffix[i],
+			Scope:           "system",
+			Bp2buildDefined: bp2BuildDefined[i],
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:  f,
-			DistFilename: distFilename[i],
-			BaseTxt:      ":non-updatable-module-lib-" + f,
-			Modules:      bootclasspath,
-			ModuleTag:    "{.module-lib" + tagSuffix[i],
-			Scope:        "module-lib",
+			TxtFilename:     f,
+			DistFilename:    distFilename[i],
+			BaseTxt:         ":non-updatable-module-lib-" + f,
+			Modules:         bootclasspath,
+			ModuleTag:       "{.module-lib" + tagSuffix[i],
+			Scope:           "module-lib",
+			Bp2buildDefined: bp2BuildDefined[i],
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:  f,
-			DistFilename: distFilename[i],
-			BaseTxt:      ":non-updatable-system-server-" + f,
-			Modules:      system_server_classpath,
-			ModuleTag:    "{.system-server" + tagSuffix[i],
-			Scope:        "system-server",
+			TxtFilename:     f,
+			DistFilename:    distFilename[i],
+			BaseTxt:         ":non-updatable-system-server-" + f,
+			Modules:         system_server_classpath,
+			ModuleTag:       "{.system-server" + tagSuffix[i],
+			Scope:           "system-server",
+			Bp2buildDefined: bp2BuildDefined[i],
 		})
 	}
 	for _, txt := range textFiles {
diff --git a/api/api_test.go b/api/api_test.go
index 1f4c2af..70f2162 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -33,6 +33,8 @@
 	t.Helper()
 	runCombinedApisTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
 		ctx.RegisterModuleType("java_defaults", java.DefaultsFactory)
+		ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	})
 }
 
@@ -44,6 +46,33 @@
     bootclasspath: ["bcp"],
     system_server_classpath: ["ssc"],
 }
+
+java_sdk_library {
+		name: "bcp",
+		srcs: ["a.java", "b.java"],
+		shared_library: false,
+}
+java_sdk_library {
+		name: "ssc",
+		srcs: ["a.java", "b.java"],
+		shared_library: false,
+}
+filegroup {
+    name: "non-updatable-current.txt",
+    srcs: ["current.txt"],
+}
+filegroup {
+    name: "non-updatable-system-current.txt",
+    srcs: ["system-current.txt"],
+}
+filegroup {
+    name: "non-updatable-module-lib-current.txt",
+    srcs: ["system-removed.txt"],
+}
+filegroup {
+    name: "non-updatable-system-server-current.txt",
+    srcs: ["system-lint-baseline.txt"],
+}
 `,
 		Filesystem: map[string]string{
 			"a/Android.bp": `
@@ -51,27 +80,35 @@
 				name: "android.jar_defaults",
 			}
 			`,
+			"api/current.txt":        "",
+			"api/removed.txt":        "",
+			"api/system-current.txt": "",
+			"api/system-removed.txt": "",
+			"api/test-current.txt":   "",
+			"api/test-removed.txt":   "",
 		},
+		StubbedBuildDefinitions:    []string{"bcp", "ssc", "non-updatable-current.txt", "non-updatable-system-current.txt", "non-updatable-module-lib-current.txt", "non-updatable-system-server-current.txt"},
+		ExpectedHandcraftedModules: []string{"foo-current.txt", "foo-system-current.txt", "foo-module-lib-current.txt", "foo-system-server-current.txt"},
 		ExpectedBazelTargets: []string{
 			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-current.txt", bp2build.AttrNameToString{
 				"scope": `"public"`,
-				"base":  `":non-updatable-current.txt__BP2BUILD__MISSING__DEP"`,
-				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+				"base":  `":non-updatable-current.txt"`,
+				"deps":  `[":bcp"]`,
 			}),
 			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-current.txt", bp2build.AttrNameToString{
 				"scope": `"system"`,
-				"base":  `":non-updatable-system-current.txt__BP2BUILD__MISSING__DEP"`,
-				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+				"base":  `":non-updatable-system-current.txt"`,
+				"deps":  `[":bcp"]`,
 			}),
 			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-module-lib-current.txt", bp2build.AttrNameToString{
 				"scope": `"module-lib"`,
-				"base":  `":non-updatable-module-lib-current.txt__BP2BUILD__MISSING__DEP"`,
-				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+				"base":  `":non-updatable-module-lib-current.txt"`,
+				"deps":  `[":bcp"]`,
 			}),
 			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-server-current.txt", bp2build.AttrNameToString{
 				"scope": `"system-server"`,
-				"base":  `":non-updatable-system-server-current.txt__BP2BUILD__MISSING__DEP"`,
-				"deps":  `[":ssc__BP2BUILD__MISSING__DEP"]`,
+				"base":  `":non-updatable-system-server-current.txt"`,
+				"deps":  `[":ssc"]`,
 			}),
 		},
 	})
diff --git a/api/javadoc-lint-baseline b/api/javadoc-lint-baseline
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/javadoc-lint-baseline
diff --git a/core/api/current.txt b/core/api/current.txt
index 2b50e38..96a9595 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -4463,7 +4463,7 @@
     method public void onProvideAssistData(android.os.Bundle);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]);
-    method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
     method @CallSuper protected void onRestart();
     method protected void onRestoreInstanceState(@NonNull android.os.Bundle);
     method public void onRestoreInstanceState(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
@@ -4505,7 +4505,7 @@
     method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent);
     method public void requestFullscreenMode(int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>);
     method public final void requestPermissions(@NonNull String[], int);
-    method public final void requestPermissions(@NonNull String[], int, int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public final void requestPermissions(@NonNull String[], int, int);
     method public final void requestShowKeyboardShortcuts();
     method @Deprecated public boolean requestVisibleBehind(boolean);
     method public final boolean requestWindowFeature(int);
@@ -4553,7 +4553,7 @@
     method public void setVrModeEnabled(boolean, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean shouldDockBigOverlays();
     method public boolean shouldShowRequestPermissionRationale(@NonNull String);
-    method public boolean shouldShowRequestPermissionRationale(@NonNull String, int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public boolean shouldShowRequestPermissionRationale(@NonNull String, int);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public boolean showAssist(android.os.Bundle);
     method @Deprecated public final void showDialog(int);
@@ -9769,7 +9769,7 @@
     method public int describeContents();
     method public void enforceCallingUid();
     method @Nullable public String getAttributionTag();
-    method public int getDeviceId();
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public int getDeviceId();
     method @Nullable public android.content.AttributionSource getNext();
     method @Nullable public String getPackageName();
     method public int getPid();
@@ -9785,7 +9785,7 @@
     ctor public AttributionSource.Builder(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource build();
     method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
-    method @NonNull public android.content.AttributionSource.Builder setDeviceId(int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") @NonNull public android.content.AttributionSource.Builder setDeviceId(int);
     method @Deprecated @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setNextAttributionSource(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
@@ -42982,7 +42982,6 @@
     field public static final String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
     field public static final String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
     field public static final String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
-    field @Deprecated public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool";
     field public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
     field public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
     field public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL = "hide_lte_plus_data_icon_bool";
@@ -44904,7 +44903,7 @@
     method public int getSubscriptionType();
     method public int getUsageSetting();
     method public boolean isEmbedded();
-    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public boolean isNtn();
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public boolean isOnlyNonTerrestrialNetwork();
     method public boolean isOpportunistic();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR;
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 57e2e73..5a4be65 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -472,6 +472,10 @@
 
 package android.telephony {
 
+  public class CarrierConfigManager {
+    field @Deprecated public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool";
+  }
+
   public class NetworkScan {
     method @Deprecated public void stop() throws android.os.RemoteException;
   }
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 40c6fa8..db751a4 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -875,7 +875,7 @@
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
     ctor public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], @Nullable android.content.AttributionSource);
-    ctor public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], int, @Nullable android.content.AttributionSource);
+    ctor @FlaggedApi("android.permission.flags.device_aware_permission_apis") public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], int, @Nullable android.content.AttributionSource);
     method public void enforceCallingPid();
   }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0f3347f..e51a41e8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.FlaggedApi;
 import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.LayoutRes;
@@ -98,6 +99,7 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.permission.flags.Flags;
 import android.service.voice.VoiceInteractionSession;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
@@ -5566,6 +5568,7 @@
      * @see #shouldShowRequestPermissionRationale
      * @see Context#DEVICE_ID_DEFAULT
      */
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
     public final void requestPermissions(@NonNull String[] permissions, int requestCode,
             int deviceId) {
         if (requestCode < 0) {
@@ -5638,6 +5641,7 @@
      *
      * @see #requestPermissions
      */
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
             @NonNull int[] grantResults, int deviceId) {
         onRequestPermissionsResult(requestCode, permissions, grantResults);
@@ -5670,6 +5674,7 @@
      * @see #requestPermissions
      * @see #onRequestPermissionsResult
      */
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
     public boolean shouldShowRequestPermissionRationale(@NonNull String permission, int deviceId) {
         final PackageManager packageManager = getDeviceId() == deviceId ? getPackageManager()
                 : createDeviceContext(deviceId).getPackageManager();
diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java
index a6a57cd..37111e9 100644
--- a/core/java/android/app/ApplicationStartInfo.java
+++ b/core/java/android/app/ApplicationStartInfo.java
@@ -473,9 +473,8 @@
      * available.
      * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available.
      * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps
-     * {@link #START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE}, {@link #START_TIMESTAMP_APPLICATION_ONCREATE},
-     * {@link #START_TIMESTAMP_BIND_APPLICATION}, and {@link #START_TIMESTAMP_FIRST_FRAME} will
-     * additionally be available.
+     * {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, {@link #START_TIMESTAMP_BIND_APPLICATION},
+     * and {@link #START_TIMESTAMP_FIRST_FRAME} will additionally be available.
      *
      * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is
      * dependant on devloper calling {@link Activity#reportFullyDrawn}.
diff --git a/core/java/android/app/GrammaticalInflectionManager.java b/core/java/android/app/GrammaticalInflectionManager.java
index bc6fe61..a55121a 100644
--- a/core/java/android/app/GrammaticalInflectionManager.java
+++ b/core/java/android/app/GrammaticalInflectionManager.java
@@ -100,7 +100,7 @@
 
     /**
      * Sets the current grammatical gender for all privileged applications. The value will be
-     * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)
+     * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)}
      *
      * @param grammaticalGender the terms of address the user preferred in system.
      *
@@ -121,8 +121,7 @@
     }
 
     /**
-     * Get the current grammatical gender of privileged application from the encrypted file,
-     * which is stored under {@link android.os.Environment#getDataSystemCeDirectory(int)}.
+     * Get the current grammatical gender of privileged application from the encrypted file.
      *
      * @return the value of grammatical gender
      *
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 93c2b5a..dd7db23 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -9195,6 +9195,12 @@
      * You can opt-out of this behavior by using {@link Notification.Builder#setColorized(boolean)}.
      * <p>
      *
+     * <p>
+     * Starting at {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM Android V} the
+     * {@link Notification#FLAG_NO_CLEAR NO_CLEAR flag} will be set for valid MediaStyle
+     * notifications.
+     * <p>
+     *
      * To use this style with your Notification, feed it to
      * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
      * <pre class="prettyprint">
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 15678a7..bfc1eec 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -31,6 +32,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.permission.PermissionManager;
+import android.permission.flags.Flags;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.Immutable;
@@ -163,6 +165,7 @@
 
     /** @hide */
     @TestApi
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
     public AttributionSource(int uid, int pid, @Nullable String packageName,
             @Nullable String attributionTag, @NonNull IBinder token,
             @Nullable String[] renouncedPermissions,
@@ -528,6 +531,7 @@
      * <p>
      * This device ID is used for permissions checking during attribution source validation.
      */
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
     public int getDeviceId() {
         return mAttributionSourceState.deviceId;
     }
@@ -715,6 +719,7 @@
          *
          * @return the builder
          */
+        @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
         public @NonNull Builder setDeviceId(int deviceId) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x12;
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 5626b94..d8534dd 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -2,6 +2,7 @@
 
 flag {
   name: "device_aware_permission_apis"
+  is_fixed_read_only: true
   namespace: "permissions"
   description: "enable device aware permission APIs"
   bug: "274852670"
@@ -19,4 +20,4 @@
     namespace: "permissions"
     description: "enable role controller in system server"
     bug: "302562590"
-}
\ No newline at end of file
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d09f0a8..b414ed4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5664,6 +5664,37 @@
         public static final String SHOW_ROTARY_INPUT = "show_rotary_input";
 
         /**
+         * The screen backlight brightness for automatic mode.
+         *
+         * <p>Value should be one of:
+         *      <ul>
+         *        <li>SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT
+         *        <li>SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL
+         *        <li>SCREEN_BRIGHTNESS_AUTOMATIC_DIM
+         *      </ul>
+         * @hide
+         */
+        public static final String SCREEN_BRIGHTNESS_FOR_ALS = "screen_brightness_for_als";
+
+        /**
+         * SCREEN_BRIGHTNESS_FOR_ALS value for automatic bright.
+         * @hide
+         */
+        public static final int SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT = 1;
+
+        /**
+         * SCREEN_BRIGHTNESS_FOR_ALS value for automatic normal.
+         * @hide
+         */
+        public static final int SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL = 2;
+
+        /**
+         * SCREEN_BRIGHTNESS_FOR_ALS value for automatic dim.
+         * @hide
+         */
+        public static final int SCREEN_BRIGHTNESS_AUTOMATIC_DIM = 3;
+
+        /**
          * Log raw orientation data from
          * {@link com.android.server.policy.WindowOrientationListener} for use with the
          * orientationplot.py tool.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afa3157..cf46bcc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -84,6 +84,7 @@
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
+import static android.view.accessibility.Flags.forceInvertColor;
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
 
@@ -154,6 +155,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.sysprop.DisplayProperties;
 import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
@@ -1744,8 +1746,23 @@
         return getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
     }
 
-    private void updateForceDarkMode() {
-        if (mAttachInfo.mThreadedRenderer == null) return;
+    /** Returns true if force dark should be enabled according to various settings */
+    @VisibleForTesting
+    public boolean isForceDarkEnabled() {
+        if (forceInvertColor()) {
+            boolean isForceInvertEnabled = Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    /* def= */ 0,
+                    UserHandle.myUserId()) == 1;
+            // Force invert ignores all developer opt-outs.
+            // We also ignore dark theme, since the app developer can override the user's preference
+            // for dark mode in configuration.uiMode. Instead, we assume that the force invert
+            // setting will be enabled at the same time dark theme is in the Settings app.
+            if (isForceInvertEnabled) {
+                return true;
+            }
+        }
 
         boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
 
@@ -1757,8 +1774,12 @@
                     && a.getBoolean(R.styleable.Theme_forceDarkAllowed, forceDarkAllowedDefault);
             a.recycle();
         }
+        return useAutoDark;
+    }
 
-        if (mAttachInfo.mThreadedRenderer.setForceDark(useAutoDark)) {
+    private void updateForceDarkMode() {
+        if (mAttachInfo.mThreadedRenderer == null) return;
+        if (mAttachInfo.mThreadedRenderer.setForceDark(isForceDarkEnabled())) {
             // TODO: Don't require regenerating all display lists to apply this setting
             invalidateWorld(mView);
         }
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
new file mode 100644
index 0000000..a0d5800
--- /dev/null
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.view.accessibility"
+
+flag {
+    namespace: "accessibility"
+    name: "force_invert_color"
+    description: "Enable force force-dark for smart inversion and dark theme everywhere"
+    bug: "239594271"
+}
\ No newline at end of file
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 9cde296..04622fd 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -44,12 +44,14 @@
         "frameworks-core-util-lib",
         "mockwebserver",
         "guava",
+        "android.view.accessibility.flags-aconfig-java",
         "androidx.core_core",
         "androidx.core_core-ktx",
         "androidx.test.espresso.core",
         "androidx.test.ext.junit",
         "androidx.test.runner",
         "androidx.test.rules",
+        "flag-junit",
         "junit-params",
         "kotlin-test",
         "mockito-target-minus-junit4",
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 2afbb47..6a9fc04 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR;
 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
@@ -38,12 +39,18 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.app.Instrumentation;
+import android.app.UiModeManager;
 import android.content.Context;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Binder;
+import android.os.SystemProperties;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+import android.util.Log;
 import android.view.WindowInsets.Side;
 import android.view.WindowInsets.Type;
 
@@ -52,9 +59,13 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -71,6 +82,10 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ViewRootImplTest {
+    private static final String TAG = "ViewRootImplTest";
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private ViewRootImpl mViewRootImpl;
     private volatile boolean mKeyReceived = false;
@@ -101,6 +116,18 @@
                 mViewRootImpl = new ViewRootImpl(sContext, sContext.getDisplayNoVerify()));
     }
 
+    @After
+    public void teardown() {
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            Settings.Secure.resetToDefaults(sContext.getContentResolver(), TAG);
+
+            var uiModeManager = sContext.getSystemService(UiModeManager.class);
+            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+
+            setForceDarkSysProp(false);
+        });
+    }
+
     @Test
     public void adjustLayoutParamsForCompatibility_layoutFullscreen() {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
@@ -400,6 +427,100 @@
         assertThat(result).isFalse();
     }
 
+    @Test
+    public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
+        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            Settings.Secure.putInt(
+                    sContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    /* value= */ 0
+            );
+            var uiModeManager = sContext.getSystemService(UiModeManager.class);
+            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+        });
+
+        sInstrumentation.runOnMainSync(() ->
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+        );
+
+        assertThat(mViewRootImpl.isForceDarkEnabled()).isFalse();
+    }
+
+    @Test
+    public void forceInvertOnDarkThemeOff_forceDarkModeEnabled() {
+        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            Settings.Secure.putInt(
+                    sContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    /* value= */ 1
+            );
+            var uiModeManager = sContext.getSystemService(UiModeManager.class);
+            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+        });
+
+        sInstrumentation.runOnMainSync(() ->
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+        );
+
+        assertThat(mViewRootImpl.isForceDarkEnabled()).isTrue();
+    }
+
+    @Test
+    public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
+        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            Settings.Secure.putInt(
+                    sContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    /* value= */ 0
+            );
+
+            // TODO(b/297556388): figure out how to set this without getting blocked by SELinux
+            assumeTrue(setForceDarkSysProp(true));
+        });
+
+        sInstrumentation.runOnMainSync(() ->
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+        );
+
+        assertThat(mViewRootImpl.isForceDarkEnabled()).isFalse();
+    }
+
+    @Test
+    public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
+        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            Settings.Secure.putInt(
+                    sContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    /* value= */ 0
+            );
+
+            assumeTrue(setForceDarkSysProp(true));
+        });
+
+        sInstrumentation.runOnMainSync(() ->
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+        );
+
+        assertThat(mViewRootImpl.isForceDarkEnabled()).isTrue();
+    }
+
+    private boolean setForceDarkSysProp(boolean isForceDarkEnabled) {
+        try {
+            SystemProperties.set(
+                    ThreadedRenderer.DEBUG_FORCE_DARK,
+                    Boolean.toString(isForceDarkEnabled)
+            );
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to set force_dark sysprop", e);
+            return false;
+        }
+    }
+
     class KeyView extends View {
         KeyView(Context context) {
             super(context);
diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS
index 6ca991d..bc17459 100644
--- a/libs/hwui/OWNERS
+++ b/libs/hwui/OWNERS
@@ -4,9 +4,8 @@
 djsollen@google.com
 jreck@google.com
 njawad@google.com
-reed@google.com
 scroggo@google.com
-stani@google.com
+sumir@google.com
 
 # For text, e.g. Typeface, Font, Minikin, etc.
 nona@google.com
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 17ce7c7..29f27f7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -120,6 +120,11 @@
         VALIDATORS.put(System.DISPLAY_COLOR_MODE_VENDOR_HINT, ANY_STRING_VALIDATOR);
         VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(System.SCREEN_BRIGHTNESS_MODE, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(
+                System.SCREEN_BRIGHTNESS_FOR_ALS,
+                new InclusiveIntegerRangeValidator(
+                        System.SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT,
+                        System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM));
         VALIDATORS.put(System.ADAPTIVE_SLEEP, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.MODE_RINGER_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c0f6231..9ddc976a 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -101,6 +101,7 @@
                     Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                    Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
                     Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
                     Settings.System.WEAR_TTS_PREWARM_ENABLED,
                     Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index a81069a..9b00b5f 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -25,6 +25,7 @@
 import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
 import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
+import static com.android.systemui.flags.Flags.NEW_AOD_TRANSITION;
 import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
@@ -99,6 +100,8 @@
     private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
 
+    private static final long FADE_OUT_DURATION_MS = 250L;
+
     private final long mLongPressTimeout;
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @NonNull private final KeyguardViewController mKeyguardViewController;
@@ -388,6 +391,16 @@
             mView.updateIcon(ICON_LOCK, true);
             mView.setContentDescription(mLockedLabel);
             mView.setVisibility(View.VISIBLE);
+        } else if (mIsDozing && mFeatureFlags.isEnabled(NEW_AOD_TRANSITION)) {
+            mView.animate()
+                    .alpha(0f)
+                    .setDuration(FADE_OUT_DURATION_MS)
+                    .withEndAction(() -> {
+                        mView.clearIcon();
+                        mView.setVisibility(View.INVISIBLE);
+                        mView.setContentDescription(null);
+                    })
+                    .start();
         } else {
             mView.clearIcon();
             mView.setVisibility(View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
index 126a1b5..6bbd40c 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
@@ -48,6 +48,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -77,9 +78,9 @@
     private final SystemPropertiesHelper mSystemProperties;
     private final ServerFlagReader mServerFlagReader;
     private final Map<String, Flag<?>> mAllFlags;
-    private final Map<String, Boolean> mBooleanFlagCache = new TreeMap<>();
-    private final Map<String, String> mStringFlagCache = new TreeMap<>();
-    private final Map<String, Integer> mIntFlagCache = new TreeMap<>();
+    private final Map<String, Boolean> mBooleanFlagCache = new ConcurrentHashMap<>();
+    private final Map<String, String> mStringFlagCache = new ConcurrentHashMap<>();
+    private final Map<String, Integer> mIntFlagCache = new ConcurrentHashMap<>();
     private final Restarter mRestarter;
 
     private final ServerFlagReader.ChangeListener mOnPropertiesChanged =
@@ -160,87 +161,92 @@
 
     private boolean isEnabledInternal(@NotNull BooleanFlag flag) {
         String name = flag.getName();
-        if (!mBooleanFlagCache.containsKey(name)) {
-            mBooleanFlagCache.put(name,
-                    readBooleanFlagInternal(flag, flag.getDefault()));
+
+        Boolean value = mBooleanFlagCache.get(name);
+        if (value == null) {
+            value = readBooleanFlagInternal(flag, flag.getDefault());
+            mBooleanFlagCache.put(name, value);
         }
 
-        return mBooleanFlagCache.get(name);
+        return value;
     }
 
     @Override
     public boolean isEnabled(@NonNull ResourceBooleanFlag flag) {
         String name = flag.getName();
-        if (!mBooleanFlagCache.containsKey(name)) {
-            mBooleanFlagCache.put(name,
-                    readBooleanFlagInternal(flag, mResources.getBoolean(flag.getResourceId())));
+        Boolean value = mBooleanFlagCache.get(name);
+        if (value == null) {
+            value = readBooleanFlagInternal(flag, mResources.getBoolean(flag.getResourceId()));
+            mBooleanFlagCache.put(name, value);
         }
 
-        return mBooleanFlagCache.get(name);
+        return value;
     }
 
     @Override
     public boolean isEnabled(@NonNull SysPropBooleanFlag flag) {
         String name = flag.getName();
-        if (!mBooleanFlagCache.containsKey(name)) {
-            // Use #readFlagValue to get the default. That will allow it to fall through to
-            // teamfood if need be.
-            mBooleanFlagCache.put(
-                    name,
+        Boolean value = mBooleanFlagCache.get(name);
+        if (value == null) {
+            value = readBooleanFlagInternal(flag,
                     mSystemProperties.getBoolean(
                             flag.getName(),
                             readBooleanFlagInternal(flag, flag.getDefault())));
+            mBooleanFlagCache.put(name, value);
         }
-
-        return mBooleanFlagCache.get(name);
+        return value;
     }
 
     @NonNull
     @Override
     public String getString(@NonNull StringFlag flag) {
         String name = flag.getName();
-        if (!mStringFlagCache.containsKey(name)) {
-            mStringFlagCache.put(name,
-                    readFlagValueInternal(name, flag.getDefault(), StringFlagSerializer.INSTANCE));
+        String value = mStringFlagCache.get(name);
+        if (value == null) {
+            value = readFlagValueInternal(name, flag.getDefault(), StringFlagSerializer.INSTANCE);
+            mStringFlagCache.put(name, value);
         }
 
-        return mStringFlagCache.get(name);
+        return value;
     }
 
     @NonNull
     @Override
     public String getString(@NonNull ResourceStringFlag flag) {
         String name = flag.getName();
-        if (!mStringFlagCache.containsKey(name)) {
-            mStringFlagCache.put(name,
-                    readFlagValueInternal(name, mResources.getString(flag.getResourceId()),
-                            StringFlagSerializer.INSTANCE));
+        String value = mStringFlagCache.get(name);
+        if (value == null) {
+            value = readFlagValueInternal(
+                    name,
+                    mResources.getString(flag.getResourceId()),
+                    StringFlagSerializer.INSTANCE);
+            mStringFlagCache.put(name, value);
         }
-
-        return mStringFlagCache.get(name);
+        return value;
     }
 
     @Override
     public int getInt(@NonNull IntFlag flag) {
         String name = flag.getName();
-        if (!mIntFlagCache.containsKey(name)) {
-            mIntFlagCache.put(name,
-                    readFlagValueInternal(name, flag.getDefault(), IntFlagSerializer.INSTANCE));
+        Integer value = mIntFlagCache.get(name);
+        if (value == null) {
+            value = readFlagValueInternal(name, flag.getDefault(), IntFlagSerializer.INSTANCE);
+            mIntFlagCache.put(name, value);
         }
 
-        return mIntFlagCache.get(name);
+        return value;
     }
 
     @Override
     public int getInt(@NonNull ResourceIntFlag flag) {
         String name = flag.getName();
-        if (!mIntFlagCache.containsKey(name)) {
-            mIntFlagCache.put(name,
-                    readFlagValueInternal(name, mResources.getInteger(flag.getResourceId()),
-                            IntFlagSerializer.INSTANCE));
+        Integer value = mIntFlagCache.get(name);
+        if (value == null) {
+            value = readFlagValueInternal(
+                    name, mResources.getInteger(flag.getResourceId()), IntFlagSerializer.INSTANCE);
+            mIntFlagCache.put(name, value);
         }
-
-        return mIntFlagCache.get(name);
+        return value;
     }
 
     /** Specific override for Boolean flags that checks against the teamfood list.*/
@@ -531,11 +537,22 @@
     @Override
     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
         pw.println("can override: true");
+
         pw.println("booleans: " + mBooleanFlagCache.size());
-        mBooleanFlagCache.forEach((key, value) -> pw.println("  sysui_flag_" + key + ": " + value));
+        // Sort our flags for dumping
+        TreeMap<String, Boolean> dumpBooleanMap = new TreeMap<>(mBooleanFlagCache);
+        dumpBooleanMap.forEach((key, value) -> pw.println("  sysui_flag_" + key + ": " + value));
+
         pw.println("Strings: " + mStringFlagCache.size());
-        mStringFlagCache.forEach((key, value) -> pw.println("  sysui_flag_" + key
+        // Sort our flags for dumping
+        TreeMap<String, String> dumpStringMap = new TreeMap<>(mStringFlagCache);
+        dumpStringMap.forEach((key, value) -> pw.println("  sysui_flag_" + key
                 + ": [length=" + value.length() + "] \"" + value + "\""));
+
+        pw.println("Integers: " + mIntFlagCache.size());
+        // Sort our flags for dumping
+        TreeMap<String, Integer> dumpIntMap = new TreeMap<>(mIntFlagCache);
+        dumpIntMap.forEach((key, value) -> pw.println("  sysui_flag_" + key + ": " + value));
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 8587329..bdd245e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -40,8 +40,8 @@
 
     // 100 - notification
     // TODO(b/297792660): Tracking Bug
-    val ADD_TRANSIENT_HUN_IN_STACK_STATE_ANIMATOR =
-        unreleasedFlag("add_transient_hun_in_stack_state_animator", teamfood = false)
+    @JvmField val UNCLEARED_TRANSIENT_HUN_FIX =
+        unreleasedFlag("uncleared_transient_hun_fix", teamfood = false)
 
     // TODO(b/298308067): Tracking Bug
     @JvmField val SWIPE_UNCLEARED_TRANSIENT_VIEW_FIX =
@@ -176,7 +176,11 @@
      */
     // TODO(b/281655028): Tracking bug
     @JvmField
-    val LIGHT_REVEAL_MIGRATION = unreleasedFlag("light_reveal_migration", teamfood = false)
+    val LIGHT_REVEAL_MIGRATION = unreleasedFlag("light_reveal_migration", teamfood = true)
+
+    // TODO(b/301915812): Tracking Bug
+    @JvmField
+    val NEW_AOD_TRANSITION = unreleasedFlag("new_aod_transition", teamfood = true)
 
     /** Flag to control the migration of face auth to modern architecture. */
     // TODO(b/262838215): Tracking bug
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index aa76702..f0d118c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -134,7 +134,14 @@
         vibratorHelper: VibratorHelper?,
     ) {
         if (!viewModel.isVisible) {
-            view.isInvisible = true
+            view.alpha = 1f
+            view
+                    .animate()
+                    .alpha(0f)
+                    .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+                    .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS)
+                    .withEndAction { view.isInvisible = true }
+                    .start()
             return
         }
 
@@ -142,11 +149,9 @@
             view.isVisible = true
             if (viewModel.animateReveal) {
                 view.alpha = 0f
-                view.translationY = view.height / 2f
                 view
                     .animate()
                     .alpha(1f)
-                    .translationY(0f)
                     .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
                     .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS)
                     .start()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 231eeb5..5ae2aba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -22,7 +22,6 @@
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
-import android.content.res.Resources
 import android.graphics.Rect
 import android.hardware.display.DisplayManager
 import android.os.Bundle
@@ -411,15 +410,52 @@
 
     private fun setUpClock(parentView: ViewGroup) {
         largeClockHostView =
-            if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW))
+            if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
                 parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view_large)
-            else createLargeClockHostView()
+            } else {
+                val hostView = FrameLayout(context)
+                hostView.layoutParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                    )
+                parentView.addView(hostView)
+                hostView
+            }
         largeClockHostView.isInvisible = true
 
         smallClockHostView =
-            if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW))
+            if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
                 parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view)
-            else createSmallClockHostView(parentView.resources)
+            } else {
+                val resources = parentView.resources
+                val hostView = FrameLayout(context)
+                val layoutParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.WRAP_CONTENT,
+                        resources.getDimensionPixelSize(
+                            com.android.systemui.customization.R.dimen.small_clock_height
+                        )
+                    )
+                layoutParams.topMargin =
+                    KeyguardPreviewSmartspaceViewModel.getStatusBarHeight(resources) +
+                        resources.getDimensionPixelSize(
+                            com.android.systemui.customization.R.dimen.small_clock_padding_top
+                        )
+                hostView.layoutParams = layoutParams
+
+                hostView.setPaddingRelative(
+                    resources.getDimensionPixelSize(
+                        com.android.systemui.customization.R.dimen.clock_padding_start
+                    ),
+                    0,
+                    0,
+                    0
+                )
+                hostView.clipChildren = false
+                parentView.addView(hostView)
+                hostView
+            }
         smallClockHostView.isInvisible = true
 
         // TODO (b/283465254): Move the listeners to KeyguardClockRepository
@@ -476,44 +512,6 @@
         onClockChanged()
     }
 
-    private fun createLargeClockHostView(): FrameLayout {
-        val hostView = FrameLayout(context)
-        hostView.layoutParams =
-            FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT,
-            )
-        return hostView
-    }
-
-    private fun createSmallClockHostView(resources: Resources): FrameLayout {
-        val hostView = FrameLayout(context)
-        val layoutParams =
-            FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.WRAP_CONTENT,
-                resources.getDimensionPixelSize(
-                    com.android.systemui.customization.R.dimen.small_clock_height
-                )
-            )
-        layoutParams.topMargin =
-            KeyguardPreviewSmartspaceViewModel.getStatusBarHeight(resources) +
-                resources.getDimensionPixelSize(
-                    com.android.systemui.customization.R.dimen.small_clock_padding_top
-                )
-        hostView.layoutParams = layoutParams
-
-        hostView.setPaddingRelative(
-            resources.getDimensionPixelSize(
-                com.android.systemui.customization.R.dimen.clock_padding_start
-            ),
-            0,
-            0,
-            0
-        )
-        hostView.clipChildren = false
-        return hostView
-    }
-
     private fun onClockChanged() {
         val clock = clockRegistry.createCurrentClock()
         clockController.clock = clock
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
index ff40f70..91ca148 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
@@ -87,7 +87,7 @@
      */
     public void init() {
         if (mWifiPickerTracker == null) {
-            mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this);
+            mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this, TAG);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt
index ddbfcef..dc2ebe5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiPickerTrackerFactory.kt
@@ -23,8 +23,8 @@
 import android.os.SimpleClock
 import androidx.lifecycle.Lifecycle
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.util.concurrency.ThreadFactory
 import com.android.systemui.util.time.SystemClock
 import com.android.wifitrackerlib.WifiPickerTracker
 import com.android.wifitrackerlib.WifiPickerTracker.WifiPickerTrackerCallback
@@ -46,7 +46,7 @@
     private val connectivityManager: ConnectivityManager,
     private val systemClock: SystemClock,
     @Main private val mainHandler: Handler,
-    @Background private val workerHandler: Handler,
+    private val threadFactory: ThreadFactory,
 ) {
     private val clock: Clock =
         object : SimpleClock(ZoneOffset.UTC) {
@@ -60,11 +60,13 @@
     /**
      * Creates a [WifiPickerTracker] instance.
      *
+     * @param name a name to identify the worker thread used for [WifiPickerTracker] operations.
      * @return a new [WifiPickerTracker] or null if [WifiManager] is null.
      */
     fun create(
         lifecycle: Lifecycle,
         listener: WifiPickerTrackerCallback,
+        name: String,
     ): WifiPickerTracker? {
         return if (wifiManager == null) {
             null
@@ -75,7 +77,10 @@
                 wifiManager,
                 connectivityManager,
                 mainHandler,
-                workerHandler,
+                // WifiPickerTracker can take tens of seconds to finish operations, so it can't use
+                // the default background handler (it would block all other background operations).
+                // Use a custom handler instead.
+                threadFactory.buildHandlerOnNewThread("WifiPickerTracker-$name"),
                 clock,
                 MAX_SCAN_AGE_MILLIS,
                 SCAN_INTERVAL_MILLIS,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
index 20241c3..5cc5e75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.Flags.NEW_AOD_TRANSITION
 import com.android.systemui.flags.ViewRefactorFlag
 import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -88,7 +89,7 @@
     private val bubblesOptional: Optional<Bubbles>,
     demoModeController: DemoModeController,
     darkIconDispatcher: DarkIconDispatcher,
-    featureFlags: FeatureFlags,
+    private val featureFlags: FeatureFlags,
     private val statusBarWindowController: StatusBarWindowController,
     private val screenOffAnimationController: ScreenOffAnimationController,
     private val shelfIconsViewModel: NotificationIconContainerShelfViewModel,
@@ -299,9 +300,12 @@
         var animate = true
         if (!bypassController.bypassEnabled) {
             animate = dozeParameters.alwaysOn && !dozeParameters.displayNeedsBlanking
-            // We only want the appear animations to happen when the notifications get fully hidden,
-            // since otherwise the unhide animation overlaps
-            animate = animate and isFullyHidden
+            if (!featureFlags.isEnabled(NEW_AOD_TRANSITION)) {
+                // We only want the appear animations to happen when the notifications get fully
+                // hidden,
+                // since otherwise the unhide animation overlaps
+                animate = animate and isFullyHidden
+            }
         }
         updateAodIconsVisibility(animate, false /* force */)
         updateAodNotificationIcons()
@@ -657,23 +661,34 @@
             aodIconsVisible = visible
             aodIcons!!.animate().cancel()
             if (animate) {
-                val wasFullyInvisible = aodIcons!!.visibility != View.VISIBLE
-                if (aodIconsVisible) {
-                    if (wasFullyInvisible) {
-                        // No fading here, let's just appear the icons instead!
-                        aodIcons!!.visibility = View.VISIBLE
-                        aodIcons!!.alpha = 1.0f
-                        appearAodIcons()
+                if (featureFlags.isEnabled(NEW_AOD_TRANSITION)) {
+                    // Let's make sure the icon are translated to 0, since we cancelled it above
+                    animateInAodIconTranslation()
+                    if (aodIconsVisible) {
+                        CrossFadeHelper.fadeIn(aodIcons)
+                    } else {
+                        CrossFadeHelper.fadeOut(aodIcons)
+                    }
+                } else {
+                    val wasFullyInvisible = aodIcons!!.visibility != View.VISIBLE
+                    if (aodIconsVisible) {
+                        if (wasFullyInvisible) {
+                            // No fading here, let's just appear the icons instead!
+                            aodIcons!!.visibility = View.VISIBLE
+                            aodIcons!!.alpha = 1.0f
+                            appearAodIcons()
+                        } else {
+                            // Let's make sure the icon are translated to 0, since we cancelled it
+                            // above
+                            animateInAodIconTranslation()
+                            // We were fading out, let's fade in instead
+                            CrossFadeHelper.fadeIn(aodIcons)
+                        }
                     } else {
                         // Let's make sure the icon are translated to 0, since we cancelled it above
                         animateInAodIconTranslation()
-                        // We were fading out, let's fade in instead
-                        CrossFadeHelper.fadeIn(aodIcons)
+                        CrossFadeHelper.fadeOut(aodIcons)
                     }
-                } else {
-                    // Let's make sure the icon are translated to 0, since we cancelled it above
-                    animateInAodIconTranslation()
-                    CrossFadeHelper.fadeOut(aodIcons)
                 }
             } else {
                 aodIcons!!.alpha = 1.0f
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index d18f991..061132f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -772,6 +772,7 @@
     /**
      * @return if the view is in heads up state, i.e either still heads upped or it's disappearing.
      */
+    @Override
     public boolean isHeadsUpState() {
         return mIsHeadsUp || mHeadsupDisappearRunning;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 5aae488..f2f55a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -621,6 +621,10 @@
         return false;
     }
 
+    public boolean isHeadsUpState() {
+        return false;
+    }
+
     public boolean isChildInGroup() {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 28f0a0c..9f95c09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -203,6 +203,8 @@
     private final ViewRefactorFlag mAnimatedInsets;
     private final ViewRefactorFlag mShelfRefactor;
 
+    private final boolean mNewAodTransition;
+
     private int mContentHeight;
     private float mIntrinsicContentHeight;
     private int mPaddingBetweenElements;
@@ -632,6 +634,7 @@
         mIsSmallLandscapeLockscreenEnabled = featureFlags.isEnabled(
                 Flags.LOCKSCREEN_ENABLE_LANDSCAPE);
         mDebugLines = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES);
+        mNewAodTransition = featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION);
         mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
         mSensitiveRevealAnimEndabled = featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
         mAnimatedInsets =
@@ -1432,12 +1435,14 @@
 
     @VisibleForTesting
     public void updateStackHeight(float endHeight, float fraction) {
-        // During the (AOD<=>LS) transition where dozeAmount is changing,
-        // apply dozeAmount to stack height instead of expansionFraction
-        // to unfurl notifications on AOD=>LS wakeup (and furl up on LS=>AOD sleep)
-        final float dozeAmount = mAmbientState.getDozeAmount();
-        if (0f < dozeAmount && dozeAmount < 1f) {
-            fraction = 1f - dozeAmount;
+        if (!mNewAodTransition) {
+            // During the (AOD<=>LS) transition where dozeAmount is changing,
+            // apply dozeAmount to stack height instead of expansionFraction
+            // to unfurl notifications on AOD=>LS wakeup (and furl up on LS=>AOD sleep)
+            final float dozeAmount = mAmbientState.getDozeAmount();
+            if (0f < dozeAmount && dozeAmount < 1f) {
+                fraction = 1f - dozeAmount;
+            }
         }
         mAmbientState.setStackHeight(
                 MathUtils.lerp(endHeight * StackScrollAlgorithm.START_FRACTION,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index f2d5394..8ca1852 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -142,7 +142,15 @@
                 viewState.setAlpha(1f);
             } else if (ambientState.isOnKeyguard()) {
                 // Adjust alpha for wakeup to lockscreen.
-                viewState.setAlpha(1f - ambientState.getHideAmount());
+                if (view.isHeadsUpState()) {
+                    // Pulsing HUN should be visible on AOD and stay visible during 
+                    // AOD=>lockscreen transition
+                    viewState.setAlpha(1f - ambientState.getHideAmount());
+                } else {
+                    // Normal notifications are hidden on AOD and should fade in during 
+                    // AOD=>lockscreen transition
+                    viewState.setAlpha(1f - ambientState.getDozeAmount());
+                }
             } else if (ambientState.isExpansionChanging()) {
                 // Adjust alpha for shade open & close.
                 float expansion = ambientState.getExpansionFraction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
index 660aa3f..1b9e5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
@@ -15,6 +15,8 @@
  */
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.flags.Flags.NEW_AOD_TRANSITION;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -109,6 +111,8 @@
 
     private final ViewRefactorFlag mShelfRefactor;
 
+    private final boolean mNewAodTransition;
+
     private int mAodIconAppearTranslation;
 
     private boolean mAnimationsEnabled;
@@ -147,6 +151,7 @@
         mContext = context;
         mStatusBarStateController = statusBarStateController;
         mShelfRefactor = new ViewRefactorFlag(featureFlags, Flags.NOTIFICATION_SHELF_REFACTOR);
+        mNewAodTransition = featureFlags.isEnabled(NEW_AOD_TRANSITION);
         mStatusBarStateController.addCallback(this);
         mMediaManager = notificationMediaManager;
         mDozeParameters = dozeParameters;
@@ -609,9 +614,11 @@
         boolean animate = true;
         if (!mBypassController.getBypassEnabled()) {
             animate = mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking();
-            // We only want the appear animations to happen when the notifications get fully hidden,
-            // since otherwise the unhide animation overlaps
-            animate &= fullyHidden;
+            if (!mNewAodTransition) {
+                // We only want the appear animations to happen when the notifications get fully
+                // hidden, since otherwise the unhide animation overlaps
+                animate &= fullyHidden;
+            }
         }
         updateAodIconsVisibility(animate, false /* force */);
         updateAodNotificationIcons();
@@ -647,23 +654,34 @@
             mAodIconsVisible = visible;
             mAodIcons.animate().cancel();
             if (animate) {
-                boolean wasFullyInvisible = mAodIcons.getVisibility() != View.VISIBLE;
-                if (mAodIconsVisible) {
-                    if (wasFullyInvisible) {
-                        // No fading here, let's just appear the icons instead!
-                        mAodIcons.setVisibility(View.VISIBLE);
-                        mAodIcons.setAlpha(1.0f);
-                        appearAodIcons();
+                if (mNewAodTransition) {
+                    // Let's make sure the icon are translated to 0, since we cancelled it above
+                    animateInAodIconTranslation();
+                    if (mAodIconsVisible) {
+                        CrossFadeHelper.fadeIn(mAodIcons);
+                    } else {
+                        CrossFadeHelper.fadeOut(mAodIcons);
+                    }
+                } else {
+                    boolean wasFullyInvisible = mAodIcons.getVisibility() != View.VISIBLE;
+                    if (mAodIconsVisible) {
+                        if (wasFullyInvisible) {
+                            // No fading here, let's just appear the icons instead!
+                            mAodIcons.setVisibility(View.VISIBLE);
+                            mAodIcons.setAlpha(1.0f);
+                            appearAodIcons();
+                        } else {
+                            // Let's make sure the icon are translated to 0, since we cancelled it
+                            // above
+                            animateInAodIconTranslation();
+                            // We were fading out, let's fade in instead
+                            CrossFadeHelper.fadeIn(mAodIcons);
+                        }
                     } else {
                         // Let's make sure the icon are translated to 0, since we cancelled it above
                         animateInAodIconTranslation();
-                        // We were fading out, let's fade in instead
-                        CrossFadeHelper.fadeIn(mAodIcons);
+                        CrossFadeHelper.fadeOut(mAodIcons);
                     }
-                } else {
-                    // Let's make sure the icon are translated to 0, since we cancelled it above
-                    animateInAodIconTranslation();
-                    CrossFadeHelper.fadeOut(mAodIcons);
                 }
             } else {
                 mAodIcons.setAlpha(1.0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 053c27c..dc4c709 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -219,6 +219,7 @@
             // We have an active remote input typed and the user clicked on the notification.
             // this was probably unintentional, so we're closing the edit text instead.
             mRemoteInputManager.closeRemoteInputs();
+            mLogger.logCloseRemoteInput(entry);
             return;
         }
         Notification notification = entry.getSbn().getNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
index d07378e..2d30a12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -72,6 +72,14 @@
         })
     }
 
+    fun logCloseRemoteInput(entry: NotificationEntry) {
+        buffer.log(TAG, DEBUG, {
+            str1 = entry.logKey
+        }, {
+            "Closing remote input for $str1"
+        })
+    }
+
     fun logExpandingBubble(entry: NotificationEntry) {
         buffer.log(TAG, DEBUG, {
             str1 = entry.logKey
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
index 9b404f1..e9e52a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
@@ -165,7 +165,7 @@
                     }
 
                 wifiPickerTracker =
-                    wifiPickerTrackerFactory.create(lifecycle, callback).apply {
+                    wifiPickerTrackerFactory.create(lifecycle, callback, "WifiRepository").apply {
                         // By default, [WifiPickerTracker] will scan to see all available wifi
                         // networks in the area. Because SysUI only needs to display the
                         // **connected** network, we don't need scans to be running (and in fact,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index a2dc776..7b920939 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -17,9 +17,11 @@
 package com.android.keyguard;
 
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
 import static com.android.keyguard.LockIconView.ICON_LOCK;
 import static com.android.keyguard.LockIconView.ICON_UNLOCK;
 import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
@@ -41,6 +43,7 @@
 import com.android.systemui.biometrics.UdfpsController;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
 import com.android.systemui.doze.util.BurnInHelperKt;
+import com.android.systemui.statusbar.StatusBarState;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -180,13 +183,14 @@
     }
 
     @Test
-    public void testLockIcon_clearsIconOnAod_whenUdfpsNotEnrolled() {
+    public void testLockIcon_clearsIconWhenUnlocked() {
         // GIVEN udfps not enrolled
         setupUdfps();
         when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(false);
 
         // GIVEN starting state for the lock icon
         setupShowLockIcon();
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
 
         // GIVEN lock icon controller is initialized and view is attached
         init(/* useMigrationFlag= */false);
@@ -194,7 +198,7 @@
         reset(mLockIconView);
 
         // WHEN the dozing state changes
-        mStatusBarStateListener.onDozingChanged(true /* isDozing */);
+        mStatusBarStateListener.onDozingChanged(false /* isDozing */);
 
         // THEN the icon is cleared
         verify(mLockIconView).clearIcon();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt
index c372f45..1213518 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
 import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.util.mockito.whenever
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
@@ -42,7 +43,7 @@
 
     /** After migration, replaces LockIconViewControllerTest version */
     @Test
-    fun testLockIcon_clearsIconOnAod_whenUdfpsNotEnrolled() =
+    fun testLockIcon_clearsIconWhenUnlocked() =
         runBlocking(IMMEDIATE) {
             // GIVEN udfps not enrolled
             setupUdfps()
@@ -50,14 +51,14 @@
 
             // GIVEN starting state for the lock icon
             setupShowLockIcon()
+            whenever(mStatusBarStateController.state).thenReturn(StatusBarState.SHADE)
 
             // GIVEN lock icon controller is initialized and view is attached
             init(/* useMigrationFlag= */ true)
             reset(mLockIconView)
 
             // WHEN the dozing state changes
-            mUnderTest.mIsDozingCallback.accept(true)
-
+            mUnderTest.mIsDozingCallback.accept(false)
             // THEN the icon is cleared
             verify(mLockIconView).clearIcon()
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
index 5b919d9..3fef1d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
@@ -72,7 +72,7 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        `when`(wifiPickerTrackerFactory.create(any(), any())).thenReturn(wifiPickerTracker)
+        `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker)
 
         `when`(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntryConnected)
         `when`(wifiPickerTracker.wifiEntries).thenReturn(ArrayList<WifiEntry>().apply {
@@ -165,7 +165,7 @@
 
     @Test
     fun testReturnEmptyListWhenNoWifiPickerTracker() {
-        `when`(wifiPickerTrackerFactory.create(any(), any())).thenReturn(null)
+        `when`(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(null)
         val otherController = AccessPointControllerImpl(
                 userManager,
                 userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 3a820e8..236bcb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -163,6 +163,7 @@
         mFeatureFlags.setDefault(Flags.SENSITIVE_REVEAL_ANIM);
         mFeatureFlags.setDefault(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS);
         mFeatureFlags.setDefault(Flags.NOTIFICATION_SHELF_REFACTOR);
+        mFeatureFlags.setDefault(Flags.NEW_AOD_TRANSITION);
 
         // Inject dependencies before initializing the layout
         mDependency.injectTestDependency(FeatureFlags.class, mFeatureFlags);
@@ -247,25 +248,7 @@
     }
 
     @Test
-    public void testUpdateStackHeight_withDozeAmount_whenDozeChanging() {
-        final float dozeAmount = 0.5f;
-        mAmbientState.setDozeAmount(dozeAmount);
-
-        final float endHeight = 8f;
-        final float expansionFraction = 1f;
-        float expected = MathUtils.lerp(
-                endHeight * StackScrollAlgorithm.START_FRACTION,
-                endHeight, dozeAmount);
-
-        mStackScroller.updateStackHeight(endHeight, expansionFraction);
-        assertThat(mAmbientState.getStackHeight()).isEqualTo(expected);
-    }
-
-    @Test
     public void testUpdateStackHeight_withExpansionAmount_whenDozeNotChanging() {
-        final float dozeAmount = 1f;
-        mAmbientState.setDozeAmount(dozeAmount);
-
         final float endHeight = 8f;
         final float expansionFraction = 0.5f;
         final float expected = MathUtils.lerp(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index a52466d..93faa77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -241,6 +241,8 @@
     fun resetViewStates_isOnKeyguard_viewBecomesTransparent() {
         ambientState.setStatusBarState(StatusBarState.KEYGUARD)
         ambientState.hideAmount = 0.25f
+        whenever(notificationRow.isHeadsUpState).thenReturn(true)
+
         stackScrollAlgorithm.initView(context)
 
         stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
@@ -283,17 +285,20 @@
         val row2 = mockExpandableNotificationRow()
         hostView.addView(row2)
 
+        whenever(row1.isHeadsUpState).thenReturn(true)
+        whenever(row2.isHeadsUpState).thenReturn(false)
+
         ambientState.setStatusBarState(StatusBarState.KEYGUARD)
         ambientState.hideAmount = 0.25f
+        ambientState.dozeAmount = 0.33f
         notificationShelf.viewState.hidden = true
         ambientState.shelf = notificationShelf
         stackScrollAlgorithm.initView(context)
 
         stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
 
-        val expected = 1f - ambientState.hideAmount
-        assertThat(row1.viewState.alpha).isEqualTo(expected)
-        assertThat(row2.viewState.alpha).isEqualTo(expected)
+        assertThat(row1.viewState.alpha).isEqualTo(1f - ambientState.hideAmount)
+        assertThat(row2.viewState.alpha).isEqualTo(1f - ambientState.dozeAmount)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
index afab623..c2f5665 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
@@ -105,7 +105,7 @@
     fun setUp() {
         featureFlags.set(Flags.INSTANT_TETHER, false)
         featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
-        whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor)))
+        whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor), any()))
             .thenReturn(wifiPickerTracker)
     }
 
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 55130e4..987507f 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -16,9 +16,6 @@
 # ServiceWatcher
 per-file ServiceWatcher.java = sooniln@google.com
 
-# Health
-per-file BatteryService.java = file:platform/hardware/interfaces:/health/aidl/OWNERS
-
 per-file *Accessibility* = file:/services/accessibility/OWNERS
 per-file *Alarm* = file:/apex/jobscheduler/OWNERS
 per-file *AppOp* = file:/core/java/android/permission/OWNERS
@@ -39,7 +36,7 @@
 per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
 per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS
 per-file PinnerService.java = file:/apct-tests/perftests/OWNERS
-per-file RescueParty.java = fdunlap@google.com, shuc@google.com, ancr@google.com, harshitmahajan@google.com
+per-file RescueParty.java = shuc@google.com, ancr@google.com, harshitmahajan@google.com
 per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS
 per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
 per-file TelephonyRegistry.java = file:/telephony/OWNERS
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a3c71c2..db69d93 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -541,6 +541,13 @@
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
     private static final long NOTIFICATION_LOG_ASSISTANT_CANCEL = 195579280L;
 
+    /**
+     * NO_CLEAR flag will be set for any media notification.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    static final long ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION = 264179692L;
+
     private static final Duration POST_WAKE_LOCK_TIMEOUT = Duration.ofSeconds(30);
 
     private IActivityManager mAm;
@@ -7189,6 +7196,12 @@
                             + "MEDIA_CONTENT_CONTROL permission");
                 }
             }
+
+            // Enforce NO_CLEAR flag on MediaStyle notification for apps with targetSdk >= V.
+            if (CompatChanges.isChangeEnabled(ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION,
+                    notificationUid)) {
+                notification.flags |= Notification.FLAG_NO_CLEAR;
+            }
         }
 
         // Ensure only allowed packages have a substitute app name
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 cee2524..bb24d51 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
@@ -41,6 +41,7 @@
 import android.os.ServiceManager
 import android.os.UserHandle
 import android.os.UserManager
+import android.permission.flags.Flags
 import android.permission.IOnPermissionsChangeListener
 import android.permission.PermissionControllerManager
 import android.permission.PermissionManager
@@ -1409,7 +1410,7 @@
         permissionName: String,
         deviceId: Int,
     ): Int {
-        return if (deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (!Flags.deviceAwarePermissionApis() || deviceId == Context.DEVICE_ID_DEFAULT) {
             with(policy) { getPermissionFlags(appId, userId, permissionName) }
         } else {
             if (permissionName !in DevicePermissionPolicy.DEVICE_AWARE_PERMISSIONS) {
@@ -1442,7 +1443,7 @@
         deviceId: Int,
         flags: Int
     ): Boolean {
-        return if (deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (!Flags.deviceAwarePermissionApis() || deviceId == Context.DEVICE_ID_DEFAULT) {
             with(policy) {
                setPermissionFlags(appId, userId, permissionName, flags)
             }
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 2dacda0..1d37f9d 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -31,6 +31,7 @@
         "androidx.test.rules",
         "hamcrest-library",
         "mockito-target-inline-minus-junit4",
+        "platform-compat-test-rules",
         "platform-test-annotations",
         "platformprotosnano",
         "statsdprotolite",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9543a2d..c98d235 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -164,6 +164,7 @@
 import android.app.usage.UsageStatsManagerInternal;
 import android.companion.AssociationInfo;
 import android.companion.ICompanionDeviceManager;
+import android.compat.testing.PlatformCompatChangeRule;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentUris;
@@ -270,11 +271,15 @@
 import com.google.android.collect.Lists;
 import com.google.common.collect.ImmutableList;
 
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
@@ -317,6 +322,9 @@
     private final int mUid = Binder.getCallingUid();
     private final @UserIdInt int mUserId = UserHandle.getUserId(mUid);
 
+    @Rule
+    public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
     private TestableNotificationManagerService mService;
     private INotificationManager mBinderService;
     private NotificationManagerInternal mInternalService;
@@ -4828,6 +4836,62 @@
     }
 
     @Test
+    @EnableCompatChanges({NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION})
+    public void testMediaStyle_enforceNoClearFlagEnabled() throws RemoteException {
+        Notification.MediaStyle style = new Notification.MediaStyle();
+        Notification.Builder nb = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setStyle(style);
+
+        NotificationRecord posted = createAndPostNotification(nb, "testMediaStyleSetNoClearFlag");
+
+        assertThat(posted.getFlags() & FLAG_NO_CLEAR).isEqualTo(FLAG_NO_CLEAR);
+    }
+
+    @Test
+    @EnableCompatChanges({NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION})
+    public void testCustomMediaStyle_enforceNoClearFlagEnabled() throws RemoteException {
+        Notification.DecoratedMediaCustomViewStyle style =
+                new Notification.DecoratedMediaCustomViewStyle();
+        Notification.Builder nb = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setStyle(style);
+
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testCustomMediaStyleSetNoClearFlag");
+
+        assertThat(posted.getFlags() & FLAG_NO_CLEAR).isEqualTo(FLAG_NO_CLEAR);
+    }
+
+    @Test
+    @DisableCompatChanges(NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION)
+    public void testMediaStyle_enforceNoClearFlagDisabled() throws RemoteException {
+        Notification.MediaStyle style = new Notification.MediaStyle();
+        Notification.Builder nb = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setStyle(style);
+
+        NotificationRecord posted = createAndPostNotification(nb, "testMediaStyleSetNoClearFlag");
+
+        assertThat(posted.getFlags() & FLAG_NO_CLEAR).isNotEqualTo(FLAG_NO_CLEAR);
+    }
+
+    @Test
+    @DisableCompatChanges(NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION)
+    public void testCustomMediaStyle_enforceNoClearFlagDisabled() throws RemoteException {
+        Notification.DecoratedMediaCustomViewStyle style =
+                new Notification.DecoratedMediaCustomViewStyle();
+        Notification.Builder nb = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                .setStyle(style);
+
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testCustomMediaStyleSetNoClearFlag");
+
+        assertThat(posted.getFlags() & FLAG_NO_CLEAR).isNotEqualTo(FLAG_NO_CLEAR);
+    }
+
+    @Test
     public void testMediaStyleRemote_hasPermission() throws RemoteException {
         String deviceName = "device";
         mContext.getTestablePermissions().setPermission(
@@ -4838,17 +4902,8 @@
                 mTestNotificationChannel.getId())
                 .setStyle(style);
 
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testMediaStyleRemoteHasPermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
-
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testMediaStyleRemoteHasPermission");
         Bundle extras = posted.getNotification().extras;
 
         assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
@@ -4866,17 +4921,8 @@
                 mTestNotificationChannel.getId())
                 .setStyle(style);
 
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testMediaStyleRemoteNoPermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
-
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testMediaStyleRemoteNoPermission");
 
         assertFalse(posted.getNotification().extras
                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
@@ -4899,17 +4945,8 @@
                 mTestNotificationChannel.getId())
                 .setStyle(style);
 
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testCustomMediaStyleRemoteNoPermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
-
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testCustomMediaStyleRemoteNoPermission");
 
         assertFalse(posted.getNotification().extras
                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
@@ -4929,16 +4966,9 @@
         Notification.Builder nb = new Notification.Builder(mContext,
                 mTestNotificationChannel.getId())
                 .addExtras(extras);
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testSubstituteAppNamePermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
 
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testSubstituteAppNameHasPermission");
 
         assertTrue(posted.getNotification().extras
                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
@@ -4955,16 +4985,9 @@
         Notification.Builder nb = new Notification.Builder(mContext,
                 mTestNotificationChannel.getId())
                 .addExtras(extras);
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testSubstituteAppNamePermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
 
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+        NotificationRecord posted = createAndPostNotification(nb,
+                "testSubstituteAppNameNoPermission");
 
         assertFalse(posted.getNotification().extras
                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
@@ -12656,6 +12679,20 @@
         verify(service, times(1)).setDNDMigrationDone(user.id);
     }
 
+    private NotificationRecord createAndPostNotification(Notification.Builder nb, String testName)
+            throws RemoteException {
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, testName, mUid, 0,
+                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
+        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
+                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+        waitForIdle();
+
+        return mService.findNotificationLocked(
+                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
+    }
+
     private static <T extends Parcelable> T parcelAndUnparcel(T source,
             Parcelable.Creator<T> creator) {
         Parcel parcel = Parcel.obtain();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a5e0638..98bbb40 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -519,8 +519,6 @@
     /**
      * Used in the Preferred Network Types menu to determine if the 2G option is displayed.
      * Value defaults to false as of Android T to discourage the use of insecure 2G protocols.
-     *
-     * @see #KEY_HIDE_ENABLE_2G
      */
     public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
 
@@ -9541,9 +9539,9 @@
      * Used to trade privacy/security against potentially reduced carrier coverage for some
      * carriers.
      *
-     * @deprecated Future versions of Android will disallow carriers from hiding this toggle
-     * because disabling 2g is a security feature that users should always have access to at
-     * their discretion.
+     * @removed This config option is no longer supported as it was hiding a security feature
+     * from users. Setting this option will not change the behavior of the Settings menu starting
+     * in Android V.
      */
     @Deprecated
     public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool";
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index de2e952..6ebf3be 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -259,7 +259,7 @@
     /**
      * Whether this subscription is used for communicating with non-terrestrial networks.
      */
-    private final boolean mIsNtn;
+    private final boolean mIsOnlyNonTerrestrialNetwork;
 
     /**
      * @hide
@@ -385,7 +385,7 @@
         this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
         this.mPortIndex = portIndex;
         this.mUsageSetting = usageSetting;
-        this.mIsNtn = false;
+        this.mIsOnlyNonTerrestrialNetwork = false;
     }
 
     /**
@@ -424,7 +424,7 @@
         this.mAreUiccApplicationsEnabled = builder.mAreUiccApplicationsEnabled;
         this.mPortIndex = builder.mPortIndex;
         this.mUsageSetting = builder.mUsageSetting;
-        this.mIsNtn = builder.mIsNtn;
+        this.mIsOnlyNonTerrestrialNetwork = builder.mIsOnlyNonTerrestrialNetwork;
     }
 
     /**
@@ -878,8 +878,8 @@
      * otherwise.
      */
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
-    public boolean isNtn() {
-        return mIsNtn;
+    public boolean isOnlyNonTerrestrialNetwork() {
+        return mIsOnlyNonTerrestrialNetwork;
     }
 
     @NonNull
@@ -918,7 +918,7 @@
                             UiccAccessRule.CREATOR))
                     .setUiccApplicationsEnabled(source.readBoolean())
                     .setUsageSetting(source.readInt())
-                    .setNtn(source.readBoolean())
+                    .setOnlyNonTerrestrialNetwork(source.readBoolean())
                     .build();
         }
 
@@ -960,7 +960,7 @@
         dest.writeTypedArray(mCarrierConfigAccessRules, flags);
         dest.writeBoolean(mAreUiccApplicationsEnabled);
         dest.writeInt(mUsageSetting);
-        dest.writeBoolean(mIsNtn);
+        dest.writeBoolean(mIsOnlyNonTerrestrialNetwork);
     }
 
     @Override
@@ -1023,7 +1023,7 @@
                 + " mType=" + SubscriptionManager.subscriptionTypeToString(mType)
                 + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled
                 + " usageSetting=" + SubscriptionManager.usageSettingToString(mUsageSetting)
-                + " ntn=" + mIsNtn
+                + " isOnlyNonTerrestrialNetwork=" + mIsOnlyNonTerrestrialNetwork
                 + "]";
     }
 
@@ -1049,7 +1049,7 @@
                 that.mNativeAccessRules) && Arrays.equals(mCarrierConfigAccessRules,
                 that.mCarrierConfigAccessRules) && Objects.equals(mGroupUuid, that.mGroupUuid)
                 && mCountryIso.equals(that.mCountryIso) && mGroupOwner.equals(that.mGroupOwner)
-                && mIsNtn == that.mIsNtn;
+                && mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork;
     }
 
     @Override
@@ -1058,7 +1058,7 @@
                 mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mIsEmbedded,
                 mCardString, mIsOpportunistic, mGroupUuid, mCountryIso, mCarrierId, mProfileClass,
                 mType, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting, mCardId,
-                mIsGroupDisabled, mIsNtn);
+                mIsGroupDisabled, mIsOnlyNonTerrestrialNetwork);
         result = 31 * result + Arrays.hashCode(mEhplmns);
         result = 31 * result + Arrays.hashCode(mHplmns);
         result = 31 * result + Arrays.hashCode(mNativeAccessRules);
@@ -1260,7 +1260,7 @@
         /**
          * {@code true} if it is a non-terrestrial network subscription, {@code false} otherwise.
          */
-        private boolean mIsNtn = false;
+        private boolean mIsOnlyNonTerrestrialNetwork = false;
 
         /**
          * Default constructor.
@@ -1304,7 +1304,7 @@
             mAreUiccApplicationsEnabled = info.mAreUiccApplicationsEnabled;
             mPortIndex = info.mPortIndex;
             mUsageSetting = info.mUsageSetting;
-            mIsNtn = info.mIsNtn;
+            mIsOnlyNonTerrestrialNetwork = info.mIsOnlyNonTerrestrialNetwork;
         }
 
         /**
@@ -1692,12 +1692,13 @@
         /**
          * Set whether the subscription is exclusively used for non-terrestrial networks or not.
          *
-         * @param isNtn {@code true} if the subscription is for NTN, {@code false} otherwise.
+         * @param isOnlyNonTerrestrialNetwork {@code true} if the subscription is for NTN,
+         * {@code false} otherwise.
          * @return The builder.
          */
         @NonNull
-        public Builder setNtn(boolean isNtn) {
-            mIsNtn = isNtn;
+        public Builder setOnlyNonTerrestrialNetwork(boolean isOnlyNonTerrestrialNetwork) {
+            mIsOnlyNonTerrestrialNetwork = isOnlyNonTerrestrialNetwork;
             return this;
         }