Merge "Fix powersave/powersave idle whitelist" into main
diff --git a/INPUT_OWNERS b/INPUT_OWNERS
index 06ead06..9b1016e 100644
--- a/INPUT_OWNERS
+++ b/INPUT_OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 136048
+# Please assign bugs to android-framework-input-triage@.
 arpitks@google.com
 asmitapoddar@google.com
 hcutts@google.com
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
index d7b1c9a2..f20b170 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
@@ -43,7 +43,6 @@
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
 
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -143,7 +142,7 @@
 
         // Always use the same server for consistency across the benchmarks.
         server = config.serverFactory().newServer(
-                ChannelType.CHANNEL, config.messageSize(), config.protocol().getProtocols(),
+                config.messageSize(), config.protocol().getProtocols(),
                 ciphers(config));
 
         server.setMessageProcessor(new ServerEndpoint.MessageProcessor() {
@@ -197,7 +196,6 @@
      */
     @Test
     @Parameters(method = "getParams")
-    @Ignore("b/351034205")
     public void time(Config config) throws Exception {
         reset();
         setup(config);
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java
index 0655f45..ba2acb8 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java
@@ -43,10 +43,10 @@
         factories.clientFactory, channelType, port, protocols, ciphers);
   }
 
-  public ServerEndpoint newServer(ChannelType channelType, int messageSize,
+  public ServerEndpoint newServer(int messageSize,
       String[] protocols, String[] ciphers) throws IOException {
     return new ServerEndpoint(factories.serverFactory, factories.serverSocketFactory,
-        channelType, messageSize, protocols, ciphers);
+        messageSize, protocols, ciphers);
   }
 
   private static final class Factories {
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java
index 3631c3f..1e4f124 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java
@@ -34,8 +34,6 @@
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 
-import org.conscrypt.ChannelType;
-
 /**
  * A simple socket-based test server.
  */
@@ -63,7 +61,6 @@
     }
 
     private final ServerSocket serverSocket;
-    private final ChannelType channelType;
     private final SSLSocketFactory socketFactory;
     private final int messageSize;
     private final String[] protocols;
@@ -78,11 +75,10 @@
     private volatile Future<?> processFuture;
 
     ServerEndpoint(SSLSocketFactory socketFactory, SSLServerSocketFactory serverSocketFactory,
-            ChannelType channelType, int messageSize, String[] protocols,
+            int messageSize, String[] protocols,
             String[] cipherSuites) throws IOException {
-        this.serverSocket = channelType.newServerSocket(serverSocketFactory);
+        this.serverSocket = serverSocketFactory.createServerSocket();
         this.socketFactory = socketFactory;
-        this.channelType = channelType;
         this.messageSize = messageSize;
         this.protocols = protocols;
         this.cipherSuites = cipherSuites;
@@ -134,7 +130,7 @@
                 if (stopping) {
                     return;
                 }
-                socket = channelType.accept(serverSocket, socketFactory);
+                socket = (SSLSocket) serverSocket.accept();
                 socket.setEnabledProtocols(protocols);
                 socket.setEnabledCipherSuites(cipherSuites);
 
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
index 8916a3c..af3c405 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
@@ -43,7 +43,6 @@
 import junitparams.JUnitParamsRunner;
 import junitparams.Parameters;
 
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -131,8 +130,7 @@
 
         final ChannelType channelType = config.channelType();
 
-        server = config.serverFactory().newServer(
-            channelType, config.messageSize(),
+        server = config.serverFactory().newServer(config.messageSize(),
             new String[] {"TLSv1.3", "TLSv1.2"}, ciphers(config));
         server.setMessageProcessor(new MessageProcessor() {
             @Override
@@ -202,7 +200,6 @@
 
     @Test
     @Parameters(method = "getParams")
-    @Ignore("b/351034205")
     public void throughput(Config config) throws Exception {
         setup(config);
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index 1653edc..9eea712 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -38,3 +38,15 @@
     ],
     certificate: "platform",
 }
+
+filegroup {
+    name: "multi_user_trace_config",
+    srcs: [
+        "trace_configs/trace_config_multi_user.textproto",
+    ],
+}
+
+prebuilt_etc {
+    name: "trace_config_multi_user.textproto",
+    src: ":multi_user_trace_config",
+}
diff --git a/api/Android.bp b/api/Android.bp
index 4b26eb4..d9966fd 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -284,7 +284,7 @@
 // These are libs from framework-internal-utils that are required (i.e. being referenced)
 // from framework-non-updatable-sources. Add more here when there's a need.
 // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular
-// dependencies gets bigger.
+// dependencies when the list gets bigger.
 android_non_updatable_stubs_libs = [
     "android.hardware.cas-V1.2-java",
     "android.hardware.health-V1.0-java-constants",
@@ -381,6 +381,11 @@
     "sdk_system_current_android",
 ]
 
+java_defaults {
+    name: "module-classpath-java-defaults",
+    libs: non_updatable_api_deps_on_modules,
+}
+
 // Defaults with module APIs in the classpath (mostly from prebuilts).
 // Suitable for compiling android-non-updatable.
 stubs_defaults {
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 8dfddf0..d991da5 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -563,8 +563,12 @@
 
 java_defaults {
     name: "android-non-updatable_from_text_defaults",
+    defaults: ["android-non-updatable-stubs-libs-defaults"],
     static_libs: ["framework-res-package-jar"],
     libs: ["stub-annotations"],
+    sdk_version: "none",
+    system_modules: "none",
+    previous_api: ":android.api.public.latest",
 }
 
 java_defaults {
@@ -582,10 +586,10 @@
         "api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_everything_from_text_defaults"],
-    full_api_surface_stub: "android_stubs_current.from-text",
     // Use full Android API not just the non-updatable API as the latter is incomplete
     // and can result in incorrect behavior.
     previous_api: ":android.api.combined.public.latest",
+    libs: ["all-modules-public-stubs"],
 }
 
 java_api_library {
@@ -596,10 +600,10 @@
         "system-api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_everything_from_text_defaults"],
-    full_api_surface_stub: "android_system_stubs_current.from-text",
     // Use full Android API not just the non-updatable API as the latter is incomplete
     // and can result in incorrect behavior.
     previous_api: ":android.api.combined.system.latest",
+    libs: ["all-modules-system-stubs"],
 }
 
 java_api_library {
@@ -611,10 +615,10 @@
         "test-api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_everything_from_text_defaults"],
-    full_api_surface_stub: "android_test_stubs_current.from-text",
     // Use full Android API not just the non-updatable API as the latter is incomplete
     // and can result in incorrect behavior.
     previous_api: ":android.api.combined.test.latest",
+    libs: ["all-modules-system-stubs"],
 }
 
 java_api_library {
@@ -625,8 +629,10 @@
         "system-api-stubs-docs-non-updatable.api.contribution",
         "module-lib-api-stubs-docs-non-updatable.api.contribution",
     ],
-    defaults: ["android-non-updatable_everything_from_text_defaults"],
-    full_api_surface_stub: "android_module_lib_stubs_current_full.from-text",
+    defaults: [
+        "module-classpath-java-defaults",
+        "android-non-updatable_everything_from_text_defaults",
+    ],
     // Use full Android API not just the non-updatable API as the latter is incomplete
     // and can result in incorrect behavior.
     previous_api: ":android.api.combined.module-lib.latest",
@@ -644,14 +650,16 @@
         "test-api-stubs-docs-non-updatable.api.contribution",
         "module-lib-api-stubs-docs-non-updatable.api.contribution",
     ],
-    defaults: ["android-non-updatable_everything_from_text_defaults"],
-    full_api_surface_stub: "android_test_module_lib_stubs_current.from-text",
+    defaults: [
+        "module-classpath-java-defaults",
+        "android-non-updatable_everything_from_text_defaults",
+    ],
 
     // No need to specify previous_api as this is not used for compiling against.
-
     // This module is only used for hiddenapi, and other modules should not
     // depend on this module.
     visibility: ["//visibility:private"],
+    libs: ["all-modules-system-stubs"],
 }
 
 java_defaults {
@@ -665,7 +673,7 @@
 }
 
 java_library {
-    name: "android_stubs_current.from-source",
+    name: "android_stubs_current",
     static_libs: [
         "all-modules-public-stubs",
         "android-non-updatable.stubs",
@@ -675,7 +683,7 @@
 }
 
 java_library {
-    name: "android_stubs_current_exportable.from-source",
+    name: "android_stubs_current_exportable",
     static_libs: [
         "all-modules-public-stubs-exportable",
         "android-non-updatable.stubs.exportable",
@@ -685,7 +693,7 @@
 }
 
 java_library {
-    name: "android_system_stubs_current.from-source",
+    name: "android_system_stubs_current",
     static_libs: [
         "all-modules-system-stubs",
         "android-non-updatable.stubs.system",
@@ -698,7 +706,7 @@
 }
 
 java_library {
-    name: "android_system_stubs_current_exportable.from-source",
+    name: "android_system_stubs_current_exportable",
     static_libs: [
         "all-modules-system-stubs-exportable",
         "android-non-updatable.stubs.exportable.system",
@@ -722,7 +730,7 @@
 }
 
 java_library {
-    name: "android_test_stubs_current.from-source",
+    name: "android_test_stubs_current",
     static_libs: [
         // Updatable modules do not have test APIs, but we want to include their SystemApis, like we
         // include the SystemApi of framework-non-updatable-sources.
@@ -739,7 +747,7 @@
 }
 
 java_library {
-    name: "android_test_stubs_current_exportable.from-source",
+    name: "android_test_stubs_current_exportable",
     static_libs: [
         // Updatable modules do not have test APIs, but we want to include their SystemApis, like we
         // include the SystemApi of framework-non-updatable-sources.
@@ -760,7 +768,7 @@
 
 // This module does not need to be copied to dist
 java_library {
-    name: "android_test_frameworks_core_stubs_current.from-source",
+    name: "android_test_frameworks_core_stubs_current",
     static_libs: [
         "all-updatable-modules-system-stubs",
         "android-non-updatable.stubs.test",
@@ -772,7 +780,7 @@
 }
 
 java_library {
-    name: "android_module_lib_stubs_current.from-source",
+    name: "android_module_lib_stubs_current",
     defaults: [
         "android.jar_defaults",
     ],
@@ -785,7 +793,7 @@
 }
 
 java_library {
-    name: "android_module_lib_stubs_current_exportable.from-source",
+    name: "android_module_lib_stubs_current_exportable",
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
@@ -801,20 +809,20 @@
 }
 
 java_library {
-    name: "android_system_server_stubs_current.from-source",
+    name: "android_system_server_stubs_current",
     defaults: [
         "android.jar_defaults",
     ],
     srcs: [":services-non-updatable-stubs"],
     installable: false,
     static_libs: [
-        "android_module_lib_stubs_current.from-source",
+        "android_module_lib_stubs_current",
     ],
     visibility: ["//frameworks/base/services"],
 }
 
 java_library {
-    name: "android_system_server_stubs_current_exportable.from-source",
+    name: "android_system_server_stubs_current_exportable",
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
@@ -822,7 +830,7 @@
     srcs: [":services-non-updatable-stubs{.exportable}"],
     installable: false,
     static_libs: [
-        "android_module_lib_stubs_current_exportable.from-source",
+        "android_module_lib_stubs_current_exportable",
     ],
     dist: {
         dir: "apistubs/android/system-server",
@@ -897,215 +905,6 @@
     },
 }
 
-//
-// Java API defaults and libraries for single tree build
-//
-
-java_defaults {
-    name: "stub-annotation-defaults",
-    libs: [
-        "stub-annotations",
-    ],
-    static_libs: [
-        // stub annotations do not contribute to the API surfaces but are statically
-        // linked in the stubs for API surfaces (see frameworks/base/StubLibraries.bp).
-        // This is because annotation processors insist on loading the classes for any
-        // annotations found, thus should exist inside android.jar.
-        "private-stub-annotations-jar",
-    ],
-    is_stubs_module: true,
-}
-
-// Listing of API domains contribution and dependencies per API surfaces
-java_defaults {
-    name: "android_test_stubs_current_contributions",
-    api_surface: "test",
-    api_contributions: [
-        "framework-virtualization.stubs.source.test.api.contribution",
-        "framework-location.stubs.source.test.api.contribution",
-    ],
-}
-
-java_defaults {
-    name: "android_test_frameworks_core_stubs_current_contributions",
-    api_surface: "test",
-    api_contributions: [
-        "test-api-stubs-docs-non-updatable.api.contribution",
-    ],
-}
-
-java_defaults {
-    name: "android_module_lib_stubs_current_contributions",
-    api_surface: "module-lib",
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-        "system-api-stubs-docs-non-updatable.api.contribution",
-        "module-lib-api-stubs-docs-non-updatable.api.contribution",
-        "art.module.public.api.stubs.source.api.contribution",
-        "art.module.public.api.stubs.source.system.api.contribution",
-        "art.module.public.api.stubs.source.module_lib.api.contribution",
-        "i18n.module.public.api.stubs.source.api.contribution",
-        "i18n.module.public.api.stubs.source.system.api.contribution",
-        "i18n.module.public.api.stubs.source.module_lib.api.contribution",
-    ],
-    previous_api: ":android.api.combined.module-lib.latest",
-}
-
-// Java API library definitions per API surface
-java_api_library {
-    name: "android_stubs_current.from-text",
-    api_surface: "public",
-    defaults: [
-        // This module is dynamically created at frameworks/base/api/api.go
-        // instead of being written out, in order to minimize edits in the codebase
-        // when there is a change in the list of modules.
-        // that contributes to an api surface.
-        "android_stubs_current_contributions",
-        "stub-annotation-defaults",
-    ],
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_system_stubs_current.from-text",
-    api_surface: "system",
-    defaults: [
-        "android_stubs_current_contributions",
-        "android_system_stubs_current_contributions",
-        "stub-annotation-defaults",
-    ],
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-        "system-api-stubs-docs-non-updatable.api.contribution",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_test_stubs_current.from-text",
-    api_surface: "test",
-    defaults: [
-        "android_stubs_current_contributions",
-        "android_system_stubs_current_contributions",
-        "android_test_stubs_current_contributions",
-        "stub-annotation-defaults",
-    ],
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-        "system-api-stubs-docs-non-updatable.api.contribution",
-        "test-api-stubs-docs-non-updatable.api.contribution",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_test_frameworks_core_stubs_current.from-text",
-    api_surface: "test",
-    defaults: [
-        "android_stubs_current_contributions",
-        "android_system_stubs_current_contributions",
-        "android_test_frameworks_core_stubs_current_contributions",
-    ],
-    libs: [
-        "stub-annotations",
-    ],
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-        "system-api-stubs-docs-non-updatable.api.contribution",
-    ],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_module_lib_stubs_current_full.from-text",
-    api_surface: "module-lib",
-    defaults: [
-        "android_stubs_current_contributions",
-        "android_system_stubs_current_contributions",
-        "android_module_lib_stubs_current_contributions_full",
-    ],
-    libs: [
-        "stub-annotations",
-    ],
-    api_contributions: [
-        "api-stubs-docs-non-updatable.api.contribution",
-        "system-api-stubs-docs-non-updatable.api.contribution",
-        "module-lib-api-stubs-docs-non-updatable.api.contribution",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_module_lib_stubs_current.from-text",
-    api_surface: "module-lib",
-    defaults: [
-        "android_module_lib_stubs_current_contributions",
-    ],
-    libs: [
-        "android_module_lib_stubs_current_full.from-text",
-        "stub-annotations",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_test_module_lib_stubs_current.from-text",
-    api_surface: "module-lib",
-    defaults: [
-        "android_stubs_current_contributions",
-        "android_system_stubs_current_contributions",
-        "android_test_stubs_current_contributions",
-        "android_module_lib_stubs_current_contributions",
-    ],
-    libs: [
-        "android_module_lib_stubs_current_full.from-text",
-        "stub-annotations",
-    ],
-    api_contributions: [
-        "test-api-stubs-docs-non-updatable.api.contribution",
-    ],
-
-    // This module is only used to build android-non-updatable.stubs.test_module_lib
-    // and other modules should not depend on this module.
-    visibility: [
-        "//visibility:private",
-    ],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
-java_api_library {
-    name: "android_system_server_stubs_current.from-text",
-    api_surface: "system-server",
-    api_contributions: [
-        "services-non-updatable-stubs.api.contribution",
-    ],
-    libs: [
-        "android_module_lib_stubs_current.from-text",
-        "stub-annotations",
-    ],
-    static_libs: [
-        "android_module_lib_stubs_current.from-text",
-    ],
-    visibility: ["//visibility:public"],
-    enable_validation: false,
-    stubs_type: "everything",
-}
-
 ////////////////////////////////////////////////////////////////////////
 // api-versions.xml generation, for public and system. This API database
 // also contains the android.test.* APIs.
diff --git a/api/api.go b/api/api.go
index b6b1a7e..5b7f534 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,9 +15,7 @@
 package api
 
 import (
-	"fmt"
 	"sort"
-	"strings"
 
 	"github.com/google/blueprint/proptools"
 
@@ -464,79 +462,6 @@
 	}
 }
 
-func createApiContributionDefaults(ctx android.LoadHookContext, modules []string) {
-	defaultsSdkKinds := []android.SdkKind{
-		android.SdkPublic, android.SdkSystem, android.SdkModule,
-	}
-	for _, sdkKind := range defaultsSdkKinds {
-		props := defaultsProps{}
-		props.Name = proptools.StringPtr(
-			sdkKind.DefaultJavaLibraryName() + "_contributions")
-		if sdkKind == android.SdkModule {
-			props.Name = proptools.StringPtr(
-				sdkKind.DefaultJavaLibraryName() + "_contributions_full")
-		}
-		props.Api_surface = proptools.StringPtr(sdkKind.String())
-		apiSuffix := ""
-		if sdkKind != android.SdkPublic {
-			apiSuffix = "." + strings.ReplaceAll(sdkKind.String(), "-", "_")
-		}
-		props.Api_contributions = transformArray(
-			modules, "", fmt.Sprintf(".stubs.source%s.api.contribution", apiSuffix))
-		props.Defaults_visibility = []string{"//visibility:public"}
-		props.Previous_api = proptools.StringPtr(":android.api.combined." + sdkKind.String() + ".latest")
-		ctx.CreateModule(java.DefaultsFactory, &props)
-	}
-}
-
-func createFullApiLibraries(ctx android.LoadHookContext) {
-	javaLibraryNames := []string{
-		"android_stubs_current",
-		"android_system_stubs_current",
-		"android_test_stubs_current",
-		"android_test_frameworks_core_stubs_current",
-		"android_module_lib_stubs_current",
-		"android_system_server_stubs_current",
-	}
-
-	for _, libraryName := range javaLibraryNames {
-		props := libraryProps{}
-		props.Name = proptools.StringPtr(libraryName)
-		staticLib := libraryName + ".from-source"
-		if ctx.Config().BuildFromTextStub() {
-			staticLib = libraryName + ".from-text"
-		}
-		props.Static_libs = []string{staticLib}
-		props.Defaults = []string{"android.jar_defaults"}
-		props.Visibility = []string{"//visibility:public"}
-		props.Is_stubs_module = proptools.BoolPtr(true)
-
-		ctx.CreateModule(java.LibraryFactory, &props)
-	}
-}
-
-func createFullExportableApiLibraries(ctx android.LoadHookContext) {
-	javaLibraryNames := []string{
-		"android_stubs_current_exportable",
-		"android_system_stubs_current_exportable",
-		"android_test_stubs_current_exportable",
-		"android_module_lib_stubs_current_exportable",
-		"android_system_server_stubs_current_exportable",
-	}
-
-	for _, libraryName := range javaLibraryNames {
-		props := libraryProps{}
-		props.Name = proptools.StringPtr(libraryName)
-		staticLib := libraryName + ".from-source"
-		props.Static_libs = []string{staticLib}
-		props.Defaults = []string{"android.jar_defaults"}
-		props.Visibility = []string{"//visibility:public"}
-		props.Is_stubs_module = proptools.BoolPtr(true)
-
-		ctx.CreateModule(java.LibraryFactory, &props)
-	}
-}
-
 func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
 	bootclasspath := a.bootclasspath(ctx)
 	system_server_classpath := a.systemServerClasspath(ctx)
@@ -562,12 +487,6 @@
 	createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
 
 	createPublicStubsSourceFilegroup(ctx, bootclasspath)
-
-	createApiContributionDefaults(ctx, bootclasspath)
-
-	createFullApiLibraries(ctx)
-
-	createFullExportableApiLibraries(ctx)
 }
 
 func combinedApisModuleFactory() android.Module {
diff --git a/api/api_test.go b/api/api_test.go
index 47d1670..fb26f82 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -52,6 +52,12 @@
 		"core.current.stubs",
 		"ext",
 		"framework",
+		"android_stubs_current",
+		"android_system_stubs_current",
+		"android_test_stubs_current",
+		"android_test_frameworks_core_stubs_current",
+		"android_module_lib_stubs_current",
+		"android_system_server_stubs_current",
 		"android_stubs_current.from-text",
 		"android_system_stubs_current.from-text",
 		"android_test_stubs_current.from-text",
@@ -190,61 +196,60 @@
 			}
 		}),
 	).RunTestWithBp(t, `
-		java_sdk_library {
-			name: "framework-foo",
-			srcs: ["a.java"],
-			public: {
-				enabled: true,
-			},
-			system: {
-				enabled: true,
-			},
-			test: {
-				enabled: true,
-			},
-			module_lib: {
-				enabled: true,
-			},
-			api_packages: [
-				"foo",
-			],
-			sdk_version: "core_current",
-			annotations_enabled: true,
-		}
+	java_sdk_library {
+		name: "framework-foo",
+		srcs: ["a.java"],
+		public: {
+			enabled: true,
+		},
+		system: {
+			enabled: true,
+		},
+		test: {
+			enabled: true,
+		},
+		module_lib: {
+			enabled: true,
+		},
+		api_packages: [
+			"foo",
+		],
+		sdk_version: "core_current",
+		annotations_enabled: true,
+	}
+	java_sdk_library {
+		name: "framework-bar",
+		srcs: ["a.java"],
+		public: {
+			enabled: true,
+		},
+		system: {
+			enabled: true,
+		},
+		test: {
+			enabled: true,
+		},
+		module_lib: {
+			enabled: true,
+		},
+		api_packages: [
+			"foo",
+		],
+		sdk_version: "core_current",
+		annotations_enabled: true,
+	}
 
-		java_sdk_library {
-			name: "framework-bar",
-			srcs: ["a.java"],
-			public: {
-				enabled: true,
-			},
-			system: {
-				enabled: true,
-			},
-			test: {
-				enabled: true,
-			},
-			module_lib: {
-				enabled: true,
-			},
-			api_packages: [
-				"foo",
+	combined_apis {
+		name: "foo",
+		bootclasspath: [
+			"framework-bar",
+		] + select(boolean_var_for_testing(), {
+			true: [
+				"framework-foo",
 			],
-			sdk_version: "core_current",
-			annotations_enabled: true,
-		}
-
-		combined_apis {
-			name: "foo",
-			bootclasspath: [
-				"framework-bar",
-			] + select(boolean_var_for_testing(), {
-				true: [
-					"framework-foo",
-				],
-				default: [],
-			}),
-		}
+			default: [],
+		}),
+	}
 	`)
 
 	subModuleDependsOnSelectAppendedModule := java.CheckModuleHasDependency(t,
diff --git a/core/TEST_MAPPING b/core/TEST_MAPPING
index fd571c9..b78659c 100644
--- a/core/TEST_MAPPING
+++ b/core/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.inputmethod"
-        },
-        {
-          "include-filter": "com.android.internal.inputmethod"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_inputmethod",
       "file_patterns": [
         "core/java/com/android/internal/inputmethod/.*",
         "core/java/android/view/inputmethod/.*",
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index a29c196..e86435e 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -153,18 +153,7 @@
             "file_patterns": ["(/|^)ContextImpl.java"]
         },
         {
-            "name": "FrameworksCoreTests",
-            "options": [
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                },
-                {
-                    "include-filter": "android.content.ContextTest"
-                }
-            ],
+            "name": "FrameworksCoreTests_context",
             "file_patterns": ["(/|^)ContextImpl.java"]
         },
         {
@@ -177,35 +166,13 @@
             ]
         },
         {
-            "name": "FrameworksCoreTests",
-            "options": [
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                },
-                {
-                    "include-filter": "android.app.KeyguardManagerTest"
-                }
-            ],
+            "name": "FrameworksCoreTests_keyguard_manager",
             "file_patterns": [
                 "(/|^)KeyguardManager.java"
             ]
         },
         {
-            "name": "FrameworksCoreTests",
-            "options": [
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                },
-                {
-                    "include-filter": "android.app.PropertyInvalidatedCacheTests"
-                }
-            ],
+            "name": "FrameworksCoreTests_property_invalidated_cache",
             "file_patterns": [
                 "(/|^)PropertyInvalidatedCache.java"
             ]
diff --git a/core/java/android/app/appfunctions/OWNERS b/core/java/android/app/appfunctions/OWNERS
new file mode 100644
index 0000000..c6827cc
--- /dev/null
+++ b/core/java/android/app/appfunctions/OWNERS
@@ -0,0 +1,6 @@
+avayvod@google.com
+oadesina@google.com
+toki@google.com
+tonymak@google.com
+mingweiliao@google.com
+anothermark@google.com
diff --git a/core/java/android/content/TEST_MAPPING b/core/java/android/content/TEST_MAPPING
index a2cfbf5..baf32a5 100644
--- a/core/java/android/content/TEST_MAPPING
+++ b/core/java/android/content/TEST_MAPPING
@@ -22,24 +22,7 @@
       "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        },
-        {
-          "include-filter": "android.content.ContextTest"
-        },
-        {
-          "include-filter": "android.content.ComponentCallbacksControllerTest"
-        },
-        {
-          "include-filter": "android.content.ContextWrapperTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_android_content",
       "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java", "(/|^)ComponentCallbacksController.java"]
     },
     {
diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS
index 53f5bb0..50b7015 100644
--- a/core/java/android/database/OWNERS
+++ b/core/java/android/database/OWNERS
@@ -1,6 +1,2 @@
 include /SQLITE_OWNERS
 
-omakoto@google.com
-jsharkey@android.com
-yamasani@google.com
-
diff --git a/core/java/android/database/sqlite/TEST_MAPPING b/core/java/android/database/sqlite/TEST_MAPPING
index 9dcf4e5..659cf6c 100644
--- a/core/java/android/database/sqlite/TEST_MAPPING
+++ b/core/java/android/database/sqlite/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
     "presubmit": [
         {
-            "name": "FrameworksCoreTests",
-            "options": [
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                },
-                {
-                    "include-filter": "android.database.sqlite.SQLiteRawStatementTest"
-                }
-            ],
+            "name": "FrameworksCoreTests_sqlite",
             "file_patterns": [
                 "(/|^)SQLiteRawStatement.java",
                 "(/|^)SQLiteDatabase.java",
diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING
index b5029a6..c84ebde 100644
--- a/core/java/android/os/TEST_MAPPING
+++ b/core/java/android/os/TEST_MAPPING
@@ -73,11 +73,7 @@
         "PowerComponents\\.java",
         "[^/]*BatteryConsumer[^/]*\\.java"
       ],
-      "name": "FrameworksCoreTests",
-      "options": [
-        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
-        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
-      ]
+      "name": "FrameworksCoreTests_battery_stats"
     },
     {
       "file_patterns": [
@@ -132,12 +128,7 @@
     },
     {
       "file_patterns": ["Environment[^/]*\\.java"],
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.os.EnvironmentTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_environment"
     }
   ],
   "postsubmit": [
diff --git a/core/java/android/security/net/config/SystemCertificateSource.java b/core/java/android/security/net/config/SystemCertificateSource.java
index 3a254c1..bdda42a 100644
--- a/core/java/android/security/net/config/SystemCertificateSource.java
+++ b/core/java/android/security/net/config/SystemCertificateSource.java
@@ -19,6 +19,8 @@
 import android.os.Environment;
 import android.os.UserHandle;
 
+import com.android.internal.util.ArrayUtils;
+
 import java.io.File;
 
 /**
@@ -45,7 +47,7 @@
         }
         File updatable_dir = new File("/apex/com.android.conscrypt/cacerts");
         if (updatable_dir.exists()
-                && !(updatable_dir.list().length == 0)) {
+                && !(ArrayUtils.isEmpty(updatable_dir.list()))) {
             return updatable_dir;
         }
         return new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts");
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 3adbd68..9f54d9f 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -24,7 +24,7 @@
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.Network;
-import android.net.NetworkInfo;
+import android.net.NetworkCapabilities;
 import android.net.SntpClient;
 import android.os.Build;
 import android.os.SystemClock;
@@ -687,8 +687,16 @@
             if (connectivityManager == null) {
                 return false;
             }
-            final NetworkInfo ni = connectivityManager.getNetworkInfo(network);
-
+            final NetworkCapabilities networkCapabilities =
+                    connectivityManager.getNetworkCapabilities(network);
+            if (networkCapabilities == null) {
+                if (LOGD) Log.d(TAG, "getNetwork: failed to get network capabilities");
+                return false;
+            }
+            final boolean isConnectedToInternet = networkCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    && networkCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_VALIDATED);
             // This connectivity check is to avoid performing a DNS lookup for the time server on a
             // unconnected network. There are races to obtain time in Android when connectivity
             // changes, which means that forceRefresh() can be called by various components before
@@ -698,8 +706,8 @@
             // A side effect of check is that tests that run a fake NTP server on the device itself
             // will only be able to use it if the active network is connected, even though loopback
             // addresses are actually reachable.
-            if (ni == null || !ni.isConnected()) {
-                if (LOGD) Log.d(TAG, "getNetwork: no connectivity");
+            if (!isConnectedToInternet) {
+                if (LOGD) Log.d(TAG, "getNetwork: no internet connectivity");
                 return false;
             }
             return true;
diff --git a/core/java/android/util/TEST_MAPPING b/core/java/android/util/TEST_MAPPING
index c681f86..64b2e6e 100644
--- a/core/java/android/util/TEST_MAPPING
+++ b/core/java/android/util/TEST_MAPPING
@@ -1,27 +1,11 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.util.CharsetUtilsTest"
-        },
-        {
-          "include-filter": "com.android.internal.util.FastDataTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_util_data_charset",
       "file_patterns": ["CharsetUtils|FastData"]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.util.XmlTest"
-        },
-        {
-          "include-filter": "android.util.BinaryXmlTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_xml",
       "file_patterns": ["Xml"]
     }
   ],
diff --git a/core/java/android/util/apk/TEST_MAPPING b/core/java/android/util/apk/TEST_MAPPING
index 7668eec..3ae470a 100644
--- a/core/java/android/util/apk/TEST_MAPPING
+++ b/core/java/android/util/apk/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.util.apk.SourceStampVerifierTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_util_apk"
     }
   ],
   "presubmit-large": [
diff --git a/core/java/android/view/textclassifier/TEST_MAPPING b/core/java/android/view/textclassifier/TEST_MAPPING
index 2f9e737..050c651 100644
--- a/core/java/android/view/textclassifier/TEST_MAPPING
+++ b/core/java/android/view/textclassifier/TEST_MAPPING
@@ -1,15 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.textclassifier"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_textclassifier"
     },
     {
       "name": "CtsTextClassifierTestCases",
diff --git a/core/java/com/android/internal/content/om/TEST_MAPPING b/core/java/com/android/internal/content/om/TEST_MAPPING
index ab3abb1..c27c325 100644
--- a/core/java/com/android/internal/content/om/TEST_MAPPING
+++ b/core/java/com/android/internal/content/om/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.content."
-        }
-      ]
+      "name": "FrameworksCoreTests_internal_content"
     },
     {
       "name": "SelfTargetingOverlayDeviceTests"
diff --git a/core/java/com/android/internal/infra/TEST_MAPPING b/core/java/com/android/internal/infra/TEST_MAPPING
index c09181f..e4550c0 100644
--- a/core/java/com/android/internal/infra/TEST_MAPPING
+++ b/core/java/com/android/internal/infra/TEST_MAPPING
@@ -20,12 +20,7 @@
       ]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.infra."
-        }
-      ]
+      "name": "FrameworksCoreTests_internal_infra"
     }
   ]
 }
diff --git a/core/java/com/android/internal/jank/TEST_MAPPING b/core/java/com/android/internal/jank/TEST_MAPPING
index 4e00ff1..e7f3dc3 100644
--- a/core/java/com/android/internal/jank/TEST_MAPPING
+++ b/core/java/com/android/internal/jank/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.jank"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ],
+      "name": "FrameworksCoreTests_internal_jank",
       "file_patterns": [
         "core/java/com/android/internal/jank/.*",
         "core/tests/coretests/src/com/android/internal/jank/.*"
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index d552e0b..cc17807 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -6,11 +6,7 @@
         "Kernel[^/]*\\.java",
         "[^/]*Power[^/]*\\.java"
       ],
-      "name": "FrameworksCoreTests",
-      "options": [
-        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
-        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
-      ]
+      "name": "FrameworksCoreTests_battery_stats"
     },
     {
       "file_patterns": [
@@ -24,11 +20,7 @@
       "file_patterns": [
         "BinderDeathDispatcher\\.java"
       ],
-      "name": "FrameworksCoreTests",
-      "options": [
-        { "include-filter": "com.android.internal.os.BinderDeathDispatcherTest" },
-        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
-      ]
+      "name": "FrameworksCoreTests_internal_os_binder"
     },
     {
       "file_patterns": [
@@ -50,25 +42,7 @@
       "name": "PowerStatsTests"
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.os.KernelCpuUidFreqTimeReaderTest"
-        },
-        {
-          "include-filter": "com.android.internal.os.KernelCpuUidActiveTimeReaderTest"
-        },
-        {
-          "include-filter": "com.android.internal.os.KernelCpuUidClusterTimeReaderTest"
-        },
-        {
-          "include-filter": "com.android.internal.os.KernelSingleUidTimeReaderTest"
-        },
-        {
-          "include-filter": "com.android.internal.os.KernelCpuUidBpfMapReaderTest"
-        }
-
-      ],
+      "name": "FrameworksCoreTests_internal_os_kernel",
       "file_patterns": [
         "KernelCpuUidTimeReader\\.java",
         "KernelCpuUidBpfMapReader\\.java",
diff --git a/core/java/com/android/internal/power/TEST_MAPPING b/core/java/com/android/internal/power/TEST_MAPPING
index 1946f5c..3f184b2 100644
--- a/core/java/com/android/internal/power/TEST_MAPPING
+++ b/core/java/com/android/internal/power/TEST_MAPPING
@@ -1,11 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
-        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
-      ]
+      "name": "FrameworksCoreTests_battery_stats"
     },
     {
       "name": "PowerStatsTests"
diff --git a/core/java/com/android/internal/security/TEST_MAPPING b/core/java/com/android/internal/security/TEST_MAPPING
index 0af3b03..5bd9d2e 100644
--- a/core/java/com/android/internal/security/TEST_MAPPING
+++ b/core/java/com/android/internal/security/TEST_MAPPING
@@ -1,15 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.security."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        }
-      ]
+      "name": "FrameworksCoreTests_internal_security"
     },
     {
       "name": "UpdatableSystemFontTest",
diff --git a/core/java/com/android/internal/util/TEST_MAPPING b/core/java/com/android/internal/util/TEST_MAPPING
index 00a8118..a0221f3b 100644
--- a/core/java/com/android/internal/util/TEST_MAPPING
+++ b/core/java/com/android/internal/util/TEST_MAPPING
@@ -5,30 +5,11 @@
       "file_patterns": ["ScreenshotHelper"]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.util.XmlTest"
-        },
-        {
-          "include-filter": "android.util.BinaryXmlTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_xml",
       "file_patterns": ["Xml"]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.util.LatencyTrackerTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ],
+      "name": "FrameworksCoreTests_internal_util_latency_tracker",
       "file_patterns": ["LatencyTracker.java"]
     }
   ]
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 30ce63c..6e67c37 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -50,6 +50,10 @@
 # Sensor
 per-file android_hardware_SensorManager* = arthuri@google.com, bduddie@google.com, stange@google.com
 
+# Security
+per-file android_os_SELinux.cpp = file:/core/java/android/security/OWNERS
+per-file android_security_* = file:/core/java/android/security/OWNERS
+
 per-file *Zygote* = file:/ZYGOTE_OWNERS
 per-file core_jni_helpers.* = file:/ZYGOTE_OWNERS
 per-file fd_utils.* = file:/ZYGOTE_OWNERS
@@ -66,7 +70,6 @@
 per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
 per-file android_os_Trace* = file:/TRACE_OWNERS
 per-file android_se_* = file:/omapi/java/android/se/OWNERS
-per-file android_security_* = file:/core/java/android/security/OWNERS
 per-file android_view_* = file:/core/java/android/view/OWNERS
 per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS
 
diff --git a/core/jni/TEST_MAPPING b/core/jni/TEST_MAPPING
index ea0b01e..fa73a4d 100644
--- a/core/jni/TEST_MAPPING
+++ b/core/jni/TEST_MAPPING
@@ -1,15 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.util.CharsetUtilsTest"
-        },
-        {
-          "include-filter": "com.android.internal.util.FastDataTest"
-        }
-      ],
+      "name": "FrameworksCoreTests_util_data_charset",
       "file_patterns": ["CharsetUtils|FastData"]
     },
     {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index dbbcbad..5d8d73b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -59,8 +59,7 @@
 #include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
diff --git a/core/tests/coretests/src/android/content/TEST_MAPPING b/core/tests/coretests/src/android/content/TEST_MAPPING
index bbc2458..fd9fda3a 100644
--- a/core/tests/coretests/src/android/content/TEST_MAPPING
+++ b/core/tests/coretests/src/android/content/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.content.ContentCaptureOptionsTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_content_capture_options"
     }
   ]
 }
diff --git a/core/tests/coretests/src/android/content/integrity/TEST_MAPPING b/core/tests/coretests/src/android/content/integrity/TEST_MAPPING
index 2920716..d22fe84 100644
--- a/core/tests/coretests/src/android/content/integrity/TEST_MAPPING
+++ b/core/tests/coretests/src/android/content/integrity/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.content.integrity."
-        }
-      ]
+      "name": "FrameworksCoreTests_android_content_integrity"
     }
   ]
 }
diff --git a/core/tests/coretests/src/android/content/pm/TEST_MAPPING b/core/tests/coretests/src/android/content/pm/TEST_MAPPING
index 978d80c..9ab438e 100644
--- a/core/tests/coretests/src/android/content/pm/TEST_MAPPING
+++ b/core/tests/coretests/src/android/content/pm/TEST_MAPPING
@@ -1,21 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.content.pm."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_android_content_pm_PreSubmit"
     }
   ],
   "postsubmit": [
diff --git a/core/tests/coretests/src/android/content/res/TEST_MAPPING b/core/tests/coretests/src/android/content/res/TEST_MAPPING
index 4ea6e40..25927de5 100644
--- a/core/tests/coretests/src/android/content/res/TEST_MAPPING
+++ b/core/tests/coretests/src/android/content/res/TEST_MAPPING
@@ -1,24 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.content.res."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.Postsubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_android_content_res"
     }
   ],
   "postsubmit": [
diff --git a/core/tests/coretests/src/android/service/TEST_MAPPING b/core/tests/coretests/src/android/service/TEST_MAPPING
index bec72d9..21f248d 100644
--- a/core/tests/coretests/src/android/service/TEST_MAPPING
+++ b/core/tests/coretests/src/android/service/TEST_MAPPING
@@ -1,17 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {"include-filter": "android.service.controls"},
-        {"include-filter": "android.service.controls.actions"},
-        {"include-filter": "android.service.controls.templates"},
-        {"include-filter": "android.service.euicc"},
-        {"include-filter": "android.service.notification"},
-        {"include-filter": "android.service.quicksettings"},
-        {"include-filter": "android.service.settings.suggestions"},
-        {"exclude-annotation": "org.junit.Ignore"}
-      ]
+      "name": "FrameworksCoreTests_android_service"
     }
   ]
 }
diff --git a/core/tests/coretests/src/android/view/contentcapture/TEST_MAPPING b/core/tests/coretests/src/android/view/contentcapture/TEST_MAPPING
index f8beac2..c2cf40d 100644
--- a/core/tests/coretests/src/android/view/contentcapture/TEST_MAPPING
+++ b/core/tests/coretests/src/android/view/contentcapture/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.contentcapture"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_android_view_contentcapture"
     }
   ]
 }
diff --git a/core/tests/coretests/src/android/view/contentprotection/TEST_MAPPING b/core/tests/coretests/src/android/view/contentprotection/TEST_MAPPING
index 3cd4e17..3ef1ac1 100644
--- a/core/tests/coretests/src/android/view/contentprotection/TEST_MAPPING
+++ b/core/tests/coretests/src/android/view/contentprotection/TEST_MAPPING
@@ -1,18 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.contentprotection"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_android_view_contentprotection"
     }
   ]
 }
diff --git a/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING b/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING
index 9aed8be..4a46244 100644
--- a/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING
+++ b/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING
@@ -1,21 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "com.android.internal.content."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksCoreTests_com_android_internal_content_Presubmit"
     }
   ]
 }
diff --git a/core/tests/coretests/src/com/android/internal/jank/CujTest.java b/core/tests/coretests/src/com/android/internal/jank/CujTest.java
index bf35ed0..2362a4c 100644
--- a/core/tests/coretests/src/com/android/internal/jank/CujTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/CujTest.java
@@ -35,7 +35,6 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -47,26 +46,30 @@
 public class CujTest {
     private static final String ENUM_NAME_PREFIX =
             "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__";
-    private static final Set<String> DEPRECATED_VALUES = new HashSet<>() {
-        {
-            add(ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION");
-        }
-    };
-    private static final Map<Integer, String> ENUM_NAME_EXCEPTION_MAP = new HashMap<>() {
-        {
-            put(Cuj.CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD"));
-            put(Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR"));
-            put(Cuj.CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH"));
-            put(Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR"));
-            put(Cuj.CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE"));
-            put(Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"));
-        }
-    };
+    private static final Set<String> DEPRECATED_VALUES = Set.of(
+            ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION"
+    );
+    private static final Map<Integer, String> ENUM_NAME_EXCEPTION_MAP = Map.ofEntries(
+            Map.entry(Cuj.CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH")),
+            Map.entry(
+                    Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR,
+                    getEnumName("SHADE_HEADS_UP_DISAPPEAR")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE")),
+            Map.entry(
+                    Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE,
+                    getEnumName("NOTIFICATION_SHADE_SWIPE")),
+            Map.entry(
+                        Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
+                        getEnumName("SHADE_QS_EXPAND_COLLAPSE")),
+            Map.entry(
+                    Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE,
+                    getEnumName("SHADE_QS_SCROLL_SWIPE")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE")),
+            Map.entry(Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"))
+    );
 
     @Rule
     public final Expect mExpect = Expect.create();
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 1410950..564b87b 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -78,6 +78,12 @@
     src: "package-shareduid-allowlist.xml",
 }
 
+prebuilt_etc {
+    name: "oem-defined-uids.xml",
+    sub_dir: "sysconfig",
+    src: "oem-defined-uids.xml",
+}
+
 // Privapp permission whitelist files
 
 prebuilt_etc {
diff --git a/data/etc/oem-defined-uids.xml b/data/etc/oem-defined-uids.xml
new file mode 100644
index 0000000..87435b9
--- /dev/null
+++ b/data/etc/oem-defined-uids.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+ -->
+
+<!--
+This XML defines a list of UIDs for OEMs to register as shared UIDs. They will be registered at the
+start of the system, which allows OEMs to create services with these UIDs. The range of these UIDs
+must be in the OEM reserved range.
+
+OEM must provide a preloaded app that is installed at boot time to retain the newly registered UID
+by adding a android:sharedUserId tag in the manifest of the preloaded app, with the value of the tag
+set to the name of the UID defined in this config file. Otherwise, the uid will be cleared at the
+end of the boot and this config file will take no effect.
+
+- The "name" XML attribute refers to the name of the shared UID. It must start with "android.uid.".
+- The "uid" XML attribute refers to the value of the shared UID. It must be in range [2900, 2999].
+
+Example usage
+    <oem-defined-uid name="android.uid.vendordata" uid="2918"/>
+    Indicates that a shared UID named "android.uid.vendordata" will be added to the system with the
+    UID of 2918.
+-->
+
+<config>
+</config>
diff --git a/graphics/java/android/graphics/drawable/TEST_MAPPING b/graphics/java/android/graphics/drawable/TEST_MAPPING
index 1018702..4f06452 100644
--- a/graphics/java/android/graphics/drawable/TEST_MAPPING
+++ b/graphics/java/android/graphics/drawable/TEST_MAPPING
@@ -12,13 +12,7 @@
     },
     {
 
-      "name": "FrameworksCoreTests",
-      "file_patterns": ["(/|^)Icon\\.java"],
-      "options" : [
-        {
-          "include-filter": "android.graphics.drawable.IconTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_drawable"
     }
   ]
 }
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 2e19d52..c6044a4 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,5 +1,5 @@
 xutan@google.com
 
 # Give submodule owners in shell resource approval
-per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com, vaniadesmonda@google.com, pbdr@google.com, tkachenkoi@google.com, mpodolian@google.com, liranb@google.com, pragyabajoria@google.com, uysalorhan@google.com, gsennton@google.com
+per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com, vaniadesmonda@google.com, pbdr@google.com, tkachenkoi@google.com, mpodolian@google.com, liranb@google.com, pragyabajoria@google.com, uysalorhan@google.com, gsennton@google.com, mattsziklay@google.com, mdehaini@google.com
 per-file res*/*/tv_*.xml = bronger@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/OWNERS
new file mode 100644
index 0000000..1875675
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/OWNERS
@@ -0,0 +1,4 @@
+# WM shell sub-module compat ui owners
+mariiasand@google.com
+gracielawputri@google.com
+mcarli@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
index 93351c3..83b5bf6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
@@ -9,3 +9,5 @@
 pragyabajoria@google.com
 uysalorhan@google.com
 gsennton@google.com
+mattsziklay@google.com
+mdehaini@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
index 4417209..3f828f5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
@@ -1 +1,3 @@
 jorgegil@google.com
+mattsziklay@google.com
+mdehaini@google.com
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index fdec969..a7206fa 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -16,3 +16,5 @@
 pragyabajoria@google.com
 uysalorhan@google.com
 gsennton@google.com
+mattsziklay@google.com
+mdehaini@google.com
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index cf7aea4..b0d1f71 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -232,6 +232,8 @@
     method public final void notifyUnhandled();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract void onDeactivated(int);
+    method @FlaggedApi("android.nfc.nfc_event_listener") public void onObserveModeStateChanged(boolean);
+    method @FlaggedApi("android.nfc.nfc_event_listener") public void onPreferredServiceChanged(boolean);
     method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
     method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.nfc.cardemulation.PollingFrame>);
     method public final void sendResponseApdu(byte[]);
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index 90ca92f..c5b82ed 100644
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -88,7 +88,7 @@
     boolean isReaderOptionEnabled();
     boolean isReaderOptionSupported();
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    boolean enableReaderOption(boolean enable);
+    boolean enableReaderOption(boolean enable, in String pkg);
     boolean isObserveModeSupported();
     boolean isObserveModeEnabled();
     boolean setObserveMode(boolean enabled, String pkg);
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index b36b705..525e2c5 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -2011,7 +2011,8 @@
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
-        return callServiceReturn(() ->  sService.enableReaderOption(enable), false);
+        return callServiceReturn(() ->
+                sService.enableReaderOption(enable, mContext.getPackageName()), false);
 
     }
 
diff --git a/nfc/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
index c3c74a6..cd8e19c 100644
--- a/nfc/java/android/nfc/cardemulation/HostApduService.java
+++ b/nfc/java/android/nfc/cardemulation/HostApduService.java
@@ -242,6 +242,16 @@
     /**
      * @hide
      */
+    public static final int MSG_OBSERVE_MODE_CHANGE = 5;
+
+    /**
+     * @hide
+     */
+    public static final int MSG_PREFERRED_SERVICE_CHANGED = 6;
+
+    /**
+     * @hide
+     */
     public static final String KEY_DATA = "data";
 
     /**
@@ -333,7 +343,17 @@
                         processPollingFrames(pollingFrames);
                     }
                     break;
-            default:
+                case MSG_OBSERVE_MODE_CHANGE:
+                    if (android.nfc.Flags.nfcEventListener()) {
+                        onObserveModeStateChanged(msg.arg1 == 1);
+                    }
+                    break;
+                case MSG_PREFERRED_SERVICE_CHANGED:
+                    if (android.nfc.Flags.nfcEventListener()) {
+                        onPreferredServiceChanged(msg.arg1 == 1);
+                    }
+                    break;
+                default:
                 super.handleMessage(msg);
             }
         }
@@ -441,4 +461,26 @@
      * @param reason Either {@link #DEACTIVATION_LINK_LOSS} or {@link #DEACTIVATION_DESELECTED}
      */
     public abstract void onDeactivated(int reason);
+
+
+    /**
+     * This method is called when this service is the preferred Nfc service and
+     * Observe mode has been enabled or disabled.
+     *
+     * @param isEnabled true if observe mode has been enabled, false if it has been disabled
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+    public void onObserveModeStateChanged(boolean isEnabled) {
+
+    }
+
+    /**
+     * This method is called when this service gains or loses preferred Nfc service status.
+     *
+     * @param isPreferred true is this service has become the preferred Nfc service,
+     * false if it is no longer the preferred service
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+    public void onPreferredServiceChanged(boolean isPreferred) {
+    }
 }
diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
index 45036a5..29699fc 100644
--- a/nfc/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -2,6 +2,14 @@
 container: "system"
 
 flag {
+    name: "nfc_event_listener"
+    is_exported: true
+    namespace: "nfc"
+    description: "Enable NFC Event listener APIs"
+    bug: "356447790"
+}
+
+flag {
     name: "enable_nfc_mainline"
     is_exported: true
     namespace: "nfc"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
index 66a2fae..c698d18 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
@@ -19,7 +19,6 @@
 
 import com.android.systemui.accessibility.accessibilitymenu.R;
 
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -52,80 +51,80 @@
     private static final int LABEL_TEXT_INDEX = 3;
 
     /** Map stores all shortcut resource IDs that is in matching order of defined shortcut. */
-    private static final Map<ShortcutId, int[]> sShortcutResource = new HashMap<>() {{
-            put(ShortcutId.ID_ASSISTANT_VALUE, new int[] {
+    private static final Map<ShortcutId, int[]> sShortcutResource = Map.ofEntries(
+            Map.entry(ShortcutId.ID_ASSISTANT_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_assistant_24dp,
                     R.color.assistant_color,
                     R.string.assistant_utterance,
                     R.string.assistant_label,
-            });
-            put(ShortcutId.ID_A11YSETTING_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_A11YSETTING_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_settings_24dp,
                     R.color.a11y_settings_color,
                     R.string.a11y_settings_label,
                     R.string.a11y_settings_label,
-            });
-            put(ShortcutId.ID_POWER_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_POWER_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_power_24dp,
                     R.color.power_color,
                     R.string.power_utterance,
                     R.string.power_label,
-            });
-            put(ShortcutId.ID_RECENT_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_RECENT_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_recent_apps_24dp,
                     R.color.recent_apps_color,
                     R.string.recent_apps_label,
                     R.string.recent_apps_label,
-            });
-            put(ShortcutId.ID_LOCKSCREEN_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_LOCKSCREEN_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_lock_24dp,
                     R.color.lockscreen_color,
                     R.string.lockscreen_label,
                     R.string.lockscreen_label,
-            });
-            put(ShortcutId.ID_QUICKSETTING_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_QUICKSETTING_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_quick_settings_24dp,
                     R.color.quick_settings_color,
                     R.string.quick_settings_label,
                     R.string.quick_settings_label,
-            });
-            put(ShortcutId.ID_NOTIFICATION_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_NOTIFICATION_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_notifications_24dp,
                     R.color.notifications_color,
                     R.string.notifications_label,
                     R.string.notifications_label,
-            });
-            put(ShortcutId.ID_SCREENSHOT_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_SCREENSHOT_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_screenshot_24dp,
                     R.color.screenshot_color,
                     R.string.screenshot_utterance,
                     R.string.screenshot_label,
-            });
-            put(ShortcutId.ID_BRIGHTNESS_UP_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_BRIGHTNESS_UP_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_brightness_up_24dp,
                     R.color.brightness_color,
                     R.string.brightness_up_label,
                     R.string.brightness_up_label,
-            });
-            put(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_brightness_down_24dp,
                     R.color.brightness_color,
                     R.string.brightness_down_label,
                     R.string.brightness_down_label,
-            });
-            put(ShortcutId.ID_VOLUME_UP_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_VOLUME_UP_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_volume_up_24dp,
                     R.color.volume_color,
                     R.string.volume_up_label,
                     R.string.volume_up_label,
-            });
-            put(ShortcutId.ID_VOLUME_DOWN_VALUE, new int[] {
+            }),
+            Map.entry(ShortcutId.ID_VOLUME_DOWN_VALUE, new int[] {
                     R.drawable.ic_logo_a11y_volume_down_24dp,
                     R.color.volume_color,
                     R.string.volume_down_label,
                     R.string.volume_down_label,
-            });
-        }};
+            })
+    );
 
     /** Shortcut id used to identify. */
     private int mShortcutId = ShortcutId.UNSPECIFIED_ID_VALUE.ordinal();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
index 317201d..f358ba2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
@@ -125,6 +125,7 @@
                 taskbarMarginLeft, taskbarMarginBottom, floatingRotationButtonPositionLeft);
 
         final int diameter = res.getDimensionPixelSize(mButtonDiameterResource);
+        mKeyButtonView.setDiameter(diameter);
         mContainerSize = diameter + Math.max(defaultMargin, Math.max(taskbarMarginLeft,
                 taskbarMarginBottom));
     }
@@ -195,6 +196,7 @@
     public void updateIcon(int lightIconColor, int darkIconColor) {
         mAnimatedDrawable = (AnimatedVectorDrawable) mKeyButtonView.getContext()
                 .getDrawable(mRotationButtonController.getIconResId());
+        mAnimatedDrawable.setBounds(0, 0, mKeyButtonView.getWidth(), mKeyButtonView.getHeight());
         mKeyButtonView.setImageDrawable(mAnimatedDrawable);
         mKeyButtonView.setColors(lightIconColor, darkIconColor);
     }
@@ -248,8 +250,14 @@
             updateDimensionResources();
 
             if (mIsShowing) {
+                updateIcon(mRotationButtonController.getLightIconColor(),
+                        mRotationButtonController.getDarkIconColor());
                 final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams();
                 mWindowManager.updateViewLayout(mKeyButtonContainer, layoutParams);
+                if (mAnimatedDrawable != null) {
+                    mAnimatedDrawable.reset();
+                    mAnimatedDrawable.start();
+                }
             }
         }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
index 2145166..75412f9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
@@ -37,6 +37,7 @@
     private static final float BACKGROUND_ALPHA = 0.92f;
 
     private KeyButtonRipple mRipple;
+    private int mDiameter;
     private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
 
     private final Configuration mLastConfiguration;
@@ -93,10 +94,25 @@
         mRipple.setDarkIntensity(darkIntensity);
     }
 
+    /**
+     * Sets the view's diameter.
+     *
+     * @param diameter the diameter value for the view
+     */
+    void setDiameter(int diameter) {
+        mDiameter = diameter;
+    }
+
     @Override
     public void draw(Canvas canvas) {
         int d = Math.min(getWidth(), getHeight());
         canvas.drawOval(0, 0, d, d, mOvalBgPaint);
         super.draw(canvas);
     }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(mDiameter, mDiameter);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS b/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS
new file mode 100644
index 0000000..443e9876
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS
@@ -0,0 +1,11 @@
+set noparent
+
+# Bug component: 78010
+
+amiko@google.com
+beverlyt@google.com
+bhinegardner@google.com
+chandruis@google.com
+jglazier@google.com
+mpietal@google.com
+tsuji@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
index 69ebb76..c4f539a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
@@ -5,3 +5,12 @@
 caitlinshk@google.com
 evanlaird@google.com
 pixel@google.com
+
+per-file *Biometrics* = set noparent
+per-file *Biometrics* = file:../keyguard/OWNERS
+per-file *Doze* = set noparent
+per-file *Doze* = file:../keyguard/OWNERS
+per-file *Keyboard* = set noparent
+per-file *Keyboard* = file:../keyguard/OWNERS
+per-file *Keyguard* = set noparent
+per-file *Keyguard* = file:../keyguard/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/OWNERS
new file mode 100644
index 0000000..4c349c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+file:../../keyguard/OWNERS
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
index 299d33f..38b4148 100644
--- a/services/accessibility/TEST_MAPPING
+++ b/services/accessibility/TEST_MAPPING
@@ -36,21 +36,7 @@
       ]
     },
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.accessibilityservice"
-        },
-        {
-          "include-filter": "android.view.accessibility"
-        },
-        {
-          "include-filter": "com.android.internal.accessibility"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_accessibility_NO_FLAKES"
     }
   ],
   "postsubmit": [
diff --git a/services/appfunctions/OWNERS b/services/appfunctions/OWNERS
new file mode 100644
index 0000000..b310894
--- /dev/null
+++ b/services/appfunctions/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/appfunctions/OWNERS
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 6f45f2a..95fb187 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -371,6 +371,10 @@
     // exempt from ECM (i.e., they will never be considered "restricted").
     private final ArraySet<SignedPackage> mEnhancedConfirmationTrustedInstallers = new ArraySet<>();
 
+    // A map of UIDs defined by OEMs, mapping from name to value. The UIDs will be registered at the
+    // start of the system which allows OEMs to create and register their system services.
+    @NonNull private final ArrayMap<String, Integer> mOemDefinedUids = new ArrayMap<>();
+
     /**
      * Map of system pre-defined, uniquely named actors; keys are namespace,
      * value maps actor name to package name.
@@ -594,6 +598,10 @@
         return mEnhancedConfirmationTrustedInstallers;
     }
 
+    @NonNull
+    public ArrayMap<String, Integer> getOemDefinedUids() {
+        return mOemDefinedUids;
+    }
     /**
      * Only use for testing. Do NOT use in production code.
      * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
@@ -1622,6 +1630,26 @@
                             }
                         }
                     } break;
+                    case "oem-defined-uid": {
+                        final String uidName = parser.getAttributeValue(null, "name");
+                        final String uidValue = parser.getAttributeValue(null, "uid");
+                        if (TextUtils.isEmpty(uidName)) {
+                            Slog.w(TAG, "<" + name + "> without valid uid name in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if (TextUtils.isEmpty(uidValue)) {
+                            Slog.w(TAG, "<" + name + "> without valid uid value in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else {
+                            try {
+                                final int oemDefinedUid = Integer.parseInt(uidValue);
+                                mOemDefinedUids.put(uidName, oemDefinedUid);
+                            } catch (NumberFormatException e) {
+                                Slog.w(TAG, "<" + name + "> with invalid uid value: "
+                                        + uidValue + " in " + permFile
+                                        + " at " + parser.getPositionDescription());
+                            }
+                        }
+                    } break;
                     case "enhanced-confirmation-trusted-package": {
                         if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()) {
                             SignedPackage signedPackage = parseEnhancedConfirmationTrustedPackage(
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 88f6bc9..5827c7f 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -297,7 +297,7 @@
     /**
      * Cache the package name and information about if it's a system module.
      */
-    @GuardedBy("mLock")
+    @GuardedBy("mSystemModulesCache")
     private final HashMap<String, Boolean> mSystemModulesCache = new HashMap<>();
 
     /**
@@ -1588,7 +1588,7 @@
         if (moduleInfos == null) {
             return;
         }
-        synchronized (mLock) {
+        synchronized (mSystemModulesCache) {
             for (ModuleInfo info : moduleInfos) {
                 mSystemModulesCache.put(info.getPackageName(), Boolean.TRUE);
             }
@@ -1596,7 +1596,7 @@
     }
 
     private boolean isSystemModule(String packageName) {
-        synchronized (mLock) {
+        synchronized (mSystemModulesCache) {
             final Boolean val = mSystemModulesCache.get(packageName);
             if (val != null) {
                 return val.booleanValue();
@@ -1624,7 +1624,7 @@
             }
         }
         // Update the cache.
-        synchronized (mLock) {
+        synchronized (mSystemModulesCache) {
             mSystemModulesCache.put(packageName, isSystemModule);
         }
         return isSystemModule;
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index feab2c05..75dc7de 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -78,11 +78,7 @@
     },
     {
       "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
-      "name": "FrameworksCoreTests",
-      "options": [
-        { "include-filter": "com.android.internal.os.BatteryStatsTests" },
-        { "exclude-annotation": "com.android.internal.os.SkipPresubmit" }
-      ]
+      "name": "FrameworksCoreTests_battery_stats"
     },
     {
       "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
index 46b4f48..4490745 100644
--- a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
+++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
@@ -17,8 +17,10 @@
 package com.android.server.hdmi;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
+
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * Buffer storage to keep incoming messages for later processing. Used to
@@ -83,6 +85,16 @@
         return false;
     }
 
+    List<HdmiCecMessage> getBufferedMessagesWithOpcode(int opcode) {
+        List<HdmiCecMessage> messages = new ArrayList<>();
+        for (HdmiCecMessage message : mBuffer) {
+            if (message.getOpcode() == opcode) {
+                messages.add(message);
+            }
+        }
+        return messages;
+    }
+
     void processAllMessages() {
         // Use the copied buffer.
         ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<>(mBuffer);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 5449089..6bc5588 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -205,7 +205,9 @@
         resetSelectRequestBuffer();
         launchDeviceDiscovery();
         startQueuedActions();
-        if (!mDelayedMessageBuffer.isBuffered(Constants.MESSAGE_ACTIVE_SOURCE)) {
+        List<HdmiCecMessage> bufferedActiveSource = mDelayedMessageBuffer
+                .getBufferedMessagesWithOpcode(Constants.MESSAGE_ACTIVE_SOURCE);
+        if (bufferedActiveSource.isEmpty()) {
             addAndStartAction(new RequestActiveSourceAction(this, new IHdmiControlCallback.Stub() {
                 @Override
                 public void onComplete(int result) {
@@ -220,9 +222,33 @@
                     }
                 }
             }));
+        } else {
+            addCecDeviceForBufferedActiveSource(bufferedActiveSource.get(0));
         }
     }
 
+    // Add a new CEC device with known information from the buffered <Active Source> message. This
+    // helps TvInputCallback#onInputAdded to be called such that the message can be processed and
+    // the TV to switch to the new active input.
+    @ServiceThreadOnly
+    private void addCecDeviceForBufferedActiveSource(HdmiCecMessage bufferedActiveSource) {
+        assertRunOnServiceThread();
+        if (bufferedActiveSource == null) {
+            return;
+        }
+        int source = bufferedActiveSource.getSource();
+        int physicalAddress = HdmiUtils.twoBytesToInt(bufferedActiveSource.getParams());
+        List<Integer> deviceTypes = HdmiUtils.getTypeFromAddress(source);
+        HdmiDeviceInfo newDevice = HdmiDeviceInfo.cecDeviceBuilder()
+                .setLogicalAddress(source)
+                .setPhysicalAddress(physicalAddress)
+                .setDisplayName(HdmiUtils.getDefaultDeviceName(source))
+                .setDeviceType(deviceTypes.get(0))
+                .setVendorId(Constants.VENDOR_ID_UNKNOWN)
+                .build();
+        mService.getHdmiCecNetwork().addCecDevice(newDevice);
+    }
+
     @ServiceThreadOnly
     public void setSelectRequestBuffer(SelectRequestBuffer requestBuffer) {
         assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index a9dff18..18a6e3dd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -486,6 +486,7 @@
      * @return true if the hour is valid
      */
     private static boolean isValidHour(int value) {
+        value = bcdToDecimal(value);
         return isWithinRange(value, 0, 23);
     }
 
@@ -497,6 +498,7 @@
      * @return true if the minute is valid
      */
     private static boolean isValidMinute(int value) {
+        value = bcdToDecimal(value);
         return isWithinRange(value, 0, 59);
     }
 
@@ -508,10 +510,24 @@
      * @return true if the duration hours is valid
      */
     private static boolean isValidDurationHours(int value) {
+        value = bcdToDecimal(value);
         return isWithinRange(value, 0, 99);
     }
 
     /**
+     * Convert BCD value to decimal value.
+     *
+     * @param value BCD value
+     * @return decimal value
+     */
+    private static int bcdToDecimal(int value) {
+        int tens = (value & 0xF0) >> 4;
+        int ones = (value & 0x0F);
+
+        return tens * 10 + ones;
+    }
+
+    /**
      * Check if the given value is a valid recording sequence. A valid value is adheres to range
      * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
      *
@@ -524,8 +540,7 @@
         if ((value & 0x80) != 0x00) {
             return false;
         }
-        // Validate than not more than one bit is set
-        return (Integer.bitCount(value) <= 1);
+        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/input/OWNERS b/services/core/java/com/android/server/input/OWNERS
index 4c20c4d..e2834ec 100644
--- a/services/core/java/com/android/server/input/OWNERS
+++ b/services/core/java/com/android/server/input/OWNERS
@@ -1 +1,2 @@
+# Bug component: 136048
 include /INPUT_OWNERS
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 365c9b5..7d2915b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -530,6 +530,12 @@
      */
     private boolean mUseDifferentDelaysForBackgroundChain;
 
+    /**
+     * Core uids and apps without the internet permission will not have any firewall rules applied
+     * to them.
+     */
+    private boolean mNeverApplyRulesToCoreUids;
+
     // See main javadoc for instructions on how to use these locks.
     final Object mUidRulesFirstLock = new Object();
     final Object mNetworkPoliciesSecondLock = new Object();
@@ -622,16 +628,6 @@
 
     @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
-    @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
-    @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
-    @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidFirewallBackgroundRules = new SparseIntArray();
-    @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidFirewallRestrictedModeRules = new SparseIntArray();
-    @GuardedBy("mUidRulesFirstLock")
-    final SparseIntArray mUidFirewallLowPowerStandbyModeRules = new SparseIntArray();
 
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mUidRulesFirstLock")
@@ -770,7 +766,8 @@
 
     /** List of apps indexed by uid and whether they have the internet permission */
     @GuardedBy("mUidRulesFirstLock")
-    private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
+    @VisibleForTesting
+    final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
 
     /**
      * Map of uid -> UidStateCallbackInfo objects holding the data received from
@@ -1048,6 +1045,7 @@
 
             mUseMeteredFirewallChains = Flags.useMeteredFirewallChains();
             mUseDifferentDelaysForBackgroundChain = Flags.useDifferentDelaysForBackgroundChain();
+            mNeverApplyRulesToCoreUids = Flags.neverApplyRulesToCoreUids();
 
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
@@ -4098,6 +4096,8 @@
                         + mUseMeteredFirewallChains);
                 fout.println(Flags.FLAG_USE_DIFFERENT_DELAYS_FOR_BACKGROUND_CHAIN + ": "
                         + mUseDifferentDelaysForBackgroundChain);
+                fout.println(Flags.FLAG_NEVER_APPLY_RULES_TO_CORE_UIDS + ": "
+                        + mNeverApplyRulesToCoreUids);
 
                 fout.println();
                 fout.println("mRestrictBackgroundLowPowerMode: " + mRestrictBackgroundLowPowerMode);
@@ -4589,7 +4589,7 @@
     @VisibleForTesting
     @GuardedBy("mUidRulesFirstLock")
     void updateRestrictedModeAllowlistUL() {
-        mUidFirewallRestrictedModeRules.clear();
+        final SparseIntArray uidRules = new SparseIntArray();
         forEachUid("updateRestrictedModeAllowlist", uid -> {
             synchronized (mUidRulesFirstLock) {
                 final int effectiveBlockedReasons = updateBlockedReasonsForRestrictedModeUL(
@@ -4599,13 +4599,13 @@
                 // setUidFirewallRulesUL will allowlist all uids that are passed to it, so only add
                 // non-default rules.
                 if (newFirewallRule != FIREWALL_RULE_DEFAULT) {
-                    mUidFirewallRestrictedModeRules.append(uid, newFirewallRule);
+                    uidRules.append(uid, newFirewallRule);
                 }
             }
         });
         if (mRestrictedNetworkingMode) {
             // firewall rules only need to be set when this mode is being enabled.
-            setUidFirewallRulesUL(FIREWALL_CHAIN_RESTRICTED, mUidFirewallRestrictedModeRules);
+            setUidFirewallRulesUL(FIREWALL_CHAIN_RESTRICTED, uidRules);
         }
         enableFirewallChainUL(FIREWALL_CHAIN_RESTRICTED, mRestrictedNetworkingMode);
     }
@@ -4689,8 +4689,7 @@
     void updateRulesForPowerSaveUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerSaveUL");
         try {
-            updateRulesForAllowlistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
-                    mUidFirewallPowerSaveRules);
+            updateRulesForAllowlistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
@@ -4705,8 +4704,7 @@
     void updateRulesForDeviceIdleUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForDeviceIdleUL");
         try {
-            updateRulesForAllowlistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
-                    mUidFirewallDozableRules);
+            updateRulesForAllowlistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
@@ -4720,13 +4718,11 @@
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for allowlisting, we can reuse their logic in this method.
     @GuardedBy("mUidRulesFirstLock")
-    private void updateRulesForAllowlistedPowerSaveUL(boolean enabled, int chain,
-            SparseIntArray rules) {
+    private void updateRulesForAllowlistedPowerSaveUL(boolean enabled, int chain) {
         if (enabled) {
             // Sync the allowlists before enabling the chain.  We don't care about the rules if
             // we are disabling the chain.
-            final SparseIntArray uidRules = rules;
-            uidRules.clear();
+            final SparseIntArray uidRules = new SparseIntArray();
             final List<UserInfo> users = mUserManager.getUsers();
             for (int ui = users.size() - 1; ui >= 0; ui--) {
                 UserInfo user = users.get(ui);
@@ -4755,9 +4751,7 @@
     private void updateRulesForBackgroundChainUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForBackgroundChainUL");
         try {
-            final SparseIntArray uidRules = mUidFirewallBackgroundRules;
-            uidRules.clear();
-
+            final SparseIntArray uidRules = new SparseIntArray();
             final List<UserInfo> users = mUserManager.getUsers();
             for (int ui = users.size() - 1; ui >= 0; ui--) {
                 final UserInfo user = users.get(ui);
@@ -4794,17 +4788,17 @@
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForLowPowerStandbyUL");
         try {
             if (mLowPowerStandbyActive) {
-                mUidFirewallLowPowerStandbyModeRules.clear();
+                final SparseIntArray uidRules = new SparseIntArray();
                 for (int i = mUidState.size() - 1; i >= 0; i--) {
                     final int uid = mUidState.keyAt(i);
                     final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid);
                     if (hasInternetPermissionUL(uid) && (effectiveBlockedReasons
                                     & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
-                        mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
+                        uidRules.put(uid, FIREWALL_RULE_ALLOW);
                     }
                 }
                 setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY,
-                        mUidFirewallLowPowerStandbyModeRules, CHAIN_TOGGLE_ENABLE);
+                        uidRules, CHAIN_TOGGLE_ENABLE);
             } else {
                 setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, null, CHAIN_TOGGLE_DISABLE);
             }
@@ -4822,10 +4816,8 @@
         final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid);
         if (mUidState.contains(uid)
                 && (effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
-            mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
             setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_ALLOW);
         } else {
-            mUidFirewallLowPowerStandbyModeRules.delete(uid);
             setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_DEFAULT);
         }
     }
@@ -4896,6 +4888,12 @@
                 int[] idleUids = mUsageStats.getIdleUidsForUser(user.id);
                 for (int uid : idleUids) {
                     if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) {
+                        if (mNeverApplyRulesToCoreUids && !isUidValidForRulesUL(uid)) {
+                            // This check is needed to keep mUidFirewallStandbyRules free of any
+                            // such uids. Doing this keeps it in sync with the actual rules applied
+                            // in the underlying connectivity stack.
+                            continue;
+                        }
                         // quick check: if this uid doesn't have INTERNET permission, it
                         // doesn't have network access anyway, so it is a waste to mess
                         // with it here.
@@ -5198,6 +5196,11 @@
 
     @GuardedBy("mUidRulesFirstLock")
     private boolean isUidValidForAllowlistRulesUL(int uid) {
+        return isUidValidForRulesUL(uid);
+    }
+
+    @GuardedBy("mUidRulesFirstLock")
+    private boolean isUidValidForRulesUL(int uid) {
         return UserHandle.isApp(uid) && hasInternetPermissionUL(uid);
     }
 
@@ -5313,16 +5316,11 @@
         mActivityManagerInternal.onUidBlockedReasonsChanged(uid, BLOCKED_REASON_NONE);
         mUidPolicy.delete(uid);
         mUidFirewallStandbyRules.delete(uid);
-        mUidFirewallDozableRules.delete(uid);
-        mUidFirewallPowerSaveRules.delete(uid);
-        mUidFirewallBackgroundRules.delete(uid);
         mBackgroundTransitioningUids.delete(uid);
         mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
         mPowerSaveWhitelistAppIds.delete(uid);
         mPowerSaveTempWhitelistAppIds.delete(uid);
         mAppIdleTempWhitelistAppIds.delete(uid);
-        mUidFirewallRestrictedModeRules.delete(uid);
-        mUidFirewallLowPowerStandbyModeRules.delete(uid);
         synchronized (mUidStateCallbackInfos) {
             mUidStateCallbackInfos.remove(uid);
         }
@@ -6217,41 +6215,33 @@
         }
     }
 
-    private void addSdkSandboxUidsIfNeeded(SparseIntArray uidRules) {
-        final int size = uidRules.size();
-        final SparseIntArray sdkSandboxUids = new SparseIntArray();
-        for (int index = 0; index < size; index++) {
-            final int uid = uidRules.keyAt(index);
-            final int rule = uidRules.valueAt(index);
-            if (Process.isApplicationUid(uid)) {
-                sdkSandboxUids.put(Process.toSdkSandboxUid(uid), rule);
-            }
-        }
-
-        for (int index = 0; index < sdkSandboxUids.size(); index++) {
-            final int uid = sdkSandboxUids.keyAt(index);
-            final int rule = sdkSandboxUids.valueAt(index);
-            uidRules.put(uid, rule);
-        }
-    }
-
     /**
      * Set uid rules on a particular firewall chain. This is going to synchronize the rules given
      * here to netd.  It will clean up dead rules and make sure the target chain only contains rules
      * specified here.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void setUidFirewallRulesUL(int chain, SparseIntArray uidRules) {
-        addSdkSandboxUidsIfNeeded(uidRules);
         try {
             int size = uidRules.size();
-            int[] uids = new int[size];
-            int[] rules = new int[size];
+            final IntArray uids = new IntArray(size);
+            final IntArray rules = new IntArray(size);
             for(int index = size - 1; index >= 0; --index) {
-                uids[index] = uidRules.keyAt(index);
-                rules[index] = uidRules.valueAt(index);
+                final int uid = uidRules.keyAt(index);
+                if (mNeverApplyRulesToCoreUids && !isUidValidForRulesUL(uid)) {
+                    continue;
+                }
+                uids.add(uid);
+                rules.add(uidRules.valueAt(index));
+                if (Process.isApplicationUid(uid)) {
+                    uids.add(Process.toSdkSandboxUid(uid));
+                    rules.add(uidRules.valueAt(index));
+                }
             }
-            mNetworkManager.setFirewallUidRules(chain, uids, rules);
-            mLogger.firewallRulesChanged(chain, uids, rules);
+            final int[] uidArray = uids.toArray();
+            final int[] ruleArray = rules.toArray();
+            mNetworkManager.setFirewallUidRules(chain, uidArray, ruleArray);
+            mLogger.firewallRulesChanged(chain, uidArray, ruleArray);
         } catch (IllegalStateException e) {
             Log.wtf(TAG, "problem setting firewall uid rules", e);
         } catch (RemoteException e) {
@@ -6264,26 +6254,17 @@
      */
     @GuardedBy("mUidRulesFirstLock")
     private void setUidFirewallRuleUL(int chain, int uid, int rule) {
+        if (mNeverApplyRulesToCoreUids && !isUidValidForRulesUL(uid)) {
+            return;
+        }
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
                     "setUidFirewallRuleUL: " + chain + "/" + uid + "/" + rule);
         }
         try {
-            if (chain == FIREWALL_CHAIN_DOZABLE) {
-                mUidFirewallDozableRules.put(uid, rule);
-            } else if (chain == FIREWALL_CHAIN_STANDBY) {
+            if (chain == FIREWALL_CHAIN_STANDBY) {
                 mUidFirewallStandbyRules.put(uid, rule);
-            } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
-                mUidFirewallPowerSaveRules.put(uid, rule);
-            } else if (chain == FIREWALL_CHAIN_RESTRICTED) {
-                mUidFirewallRestrictedModeRules.put(uid, rule);
-            } else if (chain == FIREWALL_CHAIN_LOW_POWER_STANDBY) {
-                mUidFirewallLowPowerStandbyModeRules.put(uid, rule);
-            } else if (chain == FIREWALL_CHAIN_BACKGROUND) {
-                mUidFirewallBackgroundRules.put(uid, rule);
             }
-            // Note that we do not need keep a separate cache of uid rules for chains that we do
-            // not call #setUidFirewallRulesUL for.
 
             try {
                 mNetworkManager.setFirewallUidRule(chain, uid, rule);
@@ -6328,6 +6309,8 @@
      * Resets all firewall rules associated with an UID.
      */
     private void resetUidFirewallRules(int uid) {
+        // Resetting rules for uids with isUidValidForRulesUL = false should be OK as no rules
+        // should be previously set and the downstream code will skip no-op changes.
         try {
             mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid,
                     FIREWALL_RULE_DEFAULT);
diff --git a/services/core/java/com/android/server/net/flags.aconfig b/services/core/java/com/android/server/net/flags.aconfig
index 586baf0..7f04e66 100644
--- a/services/core/java/com/android/server/net/flags.aconfig
+++ b/services/core/java/com/android/server/net/flags.aconfig
@@ -27,3 +27,13 @@
       purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "never_apply_rules_to_core_uids"
+    namespace: "backstage_power"
+    description: "Removes all rule bookkeeping and evaluation logic for core uids and uids without the internet permission"
+    bug: "356956588"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c814a1e..7ddec79 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2073,6 +2073,10 @@
         // CHECKSTYLE:ON IndentationCheck
         t.traceEnd();
 
+        t.traceBegin("get system config");
+        SystemConfig systemConfig = injector.getSystemConfig();
+        t.traceEnd();
+
         t.traceBegin("addSharedUsers");
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
@@ -2092,6 +2096,13 @@
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID,
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        final ArrayMap<String, Integer> oemDefinedUids = systemConfig.getOemDefinedUids();
+        final int numOemDefinedUids = oemDefinedUids.size();
+        for (int i = 0; i < numOemDefinedUids; i++) {
+            mSettings.addOemSharedUserLPw(oemDefinedUids.keyAt(i), oemDefinedUids.valueAt(i),
+                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        }
+
         t.traceEnd();
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
@@ -2124,10 +2135,7 @@
         mContext.getSystemService(DisplayManager.class)
                 .getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
 
-        t.traceBegin("get system config");
-        SystemConfig systemConfig = injector.getSystemConfig();
         mAvailableFeatures = systemConfig.getAvailableFeatures();
-        t.traceEnd();
 
         mProtectedPackages = new ProtectedPackages(mContext);
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index fd99c7a..200d004 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -969,6 +969,21 @@
         return null;
     }
 
+    SharedUserSetting addOemSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
+        if (!name.startsWith("android.uid")) {
+            PackageManagerService.reportSettingsProblem(Log.ERROR,
+                    "Failed to add oem defined shared user because of invalid name: " + name);
+            return null;
+        }
+        // OEM defined uids must be in the OEM reserved range
+        if (uid < 2900 || uid > 2999) {
+            PackageManagerService.reportSettingsProblem(Log.ERROR,
+                    "Failed to add oem defined shared user because of invalid uid: " + uid);
+            return null;
+        }
+        return addSharedUserLPw(name, uid, pkgFlags, pkgPrivateFlags);
+    }
+
     SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s != null) {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 7edc3a2..e7af870 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1745,8 +1745,9 @@
             // already been reset by the original hiding-transition's finishTransaction (we can't
             // show in the finishTransaction because by then the activity doesn't hide until
             // surface placement).
-            for (WindowContainer p = ar.getParent(); p != null && !containsChangeFor(p, mTargets);
-                    p = p.getParent()) {
+            for (WindowContainer p = ar.getParent();
+                 p != null && !containsChangeFor(p, mTargets) && !p.isOrganized();
+                 p = p.getParent()) {
                 if (p.getSurfaceControl() != null) {
                     transaction.show(p.getSurfaceControl());
                 }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c2b847c..f56b68b 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -183,8 +183,8 @@
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Found recents animation wallpaper target: " + w);
             mFindResults.setWallpaperTarget(w);
             return true;
-        } else if (hasWallpaper && w.isOnScreen()
-                && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+        } else if (hasWallpaper
+                && (w.mActivityRecord != null ? w.isOnScreen() : w.isReadyForDisplay())) {
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
             mFindResults.setWallpaperTarget(w);
             mFindResults.setIsWallpaperTargetForLetterbox(w.hasWallpaperForLetterboxBackground());
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 18ac0e7..4bea18a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2341,6 +2341,8 @@
             mWmService.mDisplayManagerInternal.onPresentation(dc.getDisplay().getDisplayId(),
                     /*isShown=*/ false);
         }
+        // Check if window provides non decor insets before clearing its provided insets.
+        final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
 
         // Remove this window from mTapExcludeProvidingWindows. If it was not registered, this will
         // not do anything.
@@ -2354,6 +2356,18 @@
         mWmService.postWindowRemoveCleanupLocked(this);
 
         consumeInsetsChange();
+
+        // Update the orientation when removing a window affecting the display orientation.
+        // Also recompute configuration if it provides screen decor insets.
+        boolean needToSendNewConfiguration = dc.getLastOrientationSource() == this
+                && dc.updateOrientation();
+        if (windowProvidesDisplayDecorInsets) {
+            needToSendNewConfiguration |= dc.getDisplayPolicy().updateDecorInsetsInfo();
+        }
+
+        if (needToSendNewConfiguration) {
+            dc.sendNewConfiguration();
+        }
     }
 
     @Override
@@ -2406,16 +2420,10 @@
                     mActivityRecord != null && mActivityRecord.isAnimating(PARENTS | TRANSITION),
                     mWmService.mDisplayFrozen, Debug.getCallers(6));
 
-            // Visibility of the removed window. Will be used later to update orientation later on.
-            boolean wasVisible = false;
-
             // First, see if we need to run an animation. If we do, we have to hold off on removing the
             // window until the animation is done. If the display is frozen, just remove immediately,
             // since the animation wouldn't be seen.
             if (mHasSurface && mToken.okToAnimate()) {
-                // If we are not currently running the exit animation, we need to see about starting one
-                wasVisible = isVisible();
-
                 // Remove immediately if there is display transition because the animation is
                 // usually unnoticeable (e.g. covered by rotation animation) and the animation
                 // bounds could be inconsistent, such as depending on when the window applies
@@ -2425,7 +2433,9 @@
                         // look weird if its orientation is changed.
                         && !inRelaunchingActivity();
 
-                if (wasVisible && isDisplayed()) {
+                // If we are not currently running the exit animation,
+                // we need to see about starting one
+                if (isVisible() && isDisplayed()) {
                     final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
 
                     // Try starting an animation.
@@ -2474,21 +2484,7 @@
                 }
             }
 
-            // Check if window provides non decor insets before clearing its provided insets.
-            final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
-
             removeImmediately();
-            // Removing a visible window may affect the display orientation so just update it if
-            // needed. Also recompute configuration if it provides screen decor insets.
-            boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation();
-            if (windowProvidesDisplayDecorInsets) {
-                needToSendNewConfiguration |=
-                        displayContent.getDisplayPolicy().updateDecorInsetsInfo();
-            }
-
-            if (needToSendNewConfiguration) {
-                displayContent.sendNewConfiguration();
-            }
             mWmService.updateFocusedWindowLocked(isFocused()
                             ? UPDATE_FOCUS_REMOVING_FOCUS
                             : UPDATE_FOCUS_NORMAL,
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 538c0ee..c1e2600 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -313,6 +313,7 @@
         whenever(mocks.systemConfig.defaultVrComponents).thenReturn(ArraySet())
         whenever(mocks.systemConfig.hiddenApiWhitelistedApps).thenReturn(ArraySet())
         whenever(mocks.systemConfig.appMetadataFilePaths).thenReturn(ArrayMap())
+        whenever(mocks.systemConfig.oemDefinedUids).thenReturn(ArrayMap())
         wheneverStatic { SystemProperties.set(anyString(), anyString()) }.thenDoNothing()
         wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true)
         wheneverStatic { Environment.getApexDirectory() }.thenReturn(apexDirectory)
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 01c4d1f..a4e636c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -26,6 +26,7 @@
 import static com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE;
+import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -1907,4 +1908,32 @@
         // NewDeviceAction did not start and <Give OSD Name> was not sent.
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveOsdName);
     }
+
+    @Test
+    public void onOneTouchPlay_wakeUp_addCecDevice() {
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
+                HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED);
+        mPowerManager.setInteractive(false);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(ADDR_PLAYBACK_1,
+                mTvLogicalAddress);
+        HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+                0x1000);
+        assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(textViewOn)).isEqualTo(Constants.HANDLED);
+        assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(activeSource)).isEqualTo(
+                Constants.HANDLED);
+        mTestLooper.dispatchAll();
+        assertThat(mPowerManager.isInteractive()).isTrue();
+
+        // FakePowerManagerWrapper#wakeUp() doesn't broadcast Intent.ACTION_SCREEN_ON so we have to
+        // manually call this method.
+        mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index 0aa72d0..2446d2e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -239,6 +239,9 @@
     public void isValid_setAnalogueTimer_clearAnalogueTimer() {
         assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:13:AD:06").isEqualTo(OK);
         assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:03:34").isEqualTo(OK);
+        // Allow [Recording Sequence] set multiple days of the week.
+        // e.g. Monday (0x02) | Tuesday (0x04) -> Monday or Tuesday (0x06)
+        assertMessageValidity("04:34:04:0C:16:0F:08:37:06:02:EA:60:03:34").isEqualTo(OK);
 
         assertMessageValidity("0F:33:0C:08:10:1E:04:30:08:00:13:AD:06")
                 .isEqualTo(ERROR_DESTINATION);
@@ -246,120 +249,120 @@
         assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06")
                 .isEqualTo(ERROR_PARAMETER_SHORT);
         // Out of range Day of Month
-        assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:20:0C:22:15:08:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
         // Out of range Month of Year
-        assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:33:0C:00:16:30:04:48:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Hour
-        assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:04:0C:24:15:08:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Minute
-        assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:33:0C:08:16:60:04:48:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Duration Hours
-        assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:04:0C:22:15:9A:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Minute
-        assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:33:0C:08:16:30:04:60:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:04:0C:22:15:08:55:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:33:0C:08:16:30:04:48:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
         // Out of range Analogue Broadcast Type
-        assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:04:0C:22:15:08:55:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER);
         // Out of range Analogue Frequency
-        assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:33:0C:08:16:30:04:48:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER);
         // Out of range Broadcast System
-        assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:34:04:0C:22:15:08:55:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
     }
 
     @Test
     public void isValid_setDigitalTimer_clearDigitalTimer() {
         // Services identified by Digital IDs - ARIB Broadcast System
-        assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK);
+        assertMessageValidity("04:99:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75:30").isEqualTo(OK);
         // Service identified by Digital IDs - ATSC Broadcast System
-        assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK);
+        assertMessageValidity("04:97:1E:07:18:32:80:40:01:01:8B:5E:39:5A").isEqualTo(OK);
         // Service identified by Digital IDs - DVB Broadcast System
-        assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK);
+        assertMessageValidity("04:99:05:0C:06:10:25:59:40:19:8B:44:03:11:04:FC").isEqualTo(OK);
         // Service identified by Channel - 1 part channel number
-        assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK);
+        assertMessageValidity("04:97:12:06:12:45:90:25:08:91:04:00:B1").isEqualTo(OK);
         // Service identified by Channel - 2 part channel number
-        assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK);
+        assertMessageValidity("04:99:15:09:00:15:00:45:04:82:09:C8:72:C8").isEqualTo(OK);
 
-        assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30")
+        assertMessageValidity("4F:97:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75:30")
                 .isEqualTo(ERROR_DESTINATION);
-        assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("F0:99:15:09:00:15:00:45:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE);
         assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A")
                 .isEqualTo(ERROR_PARAMETER_SHORT);
         // Out of range Day of Month
-        assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC")
+        assertMessageValidity("04:99:24:0C:06:10:25:59:40:19:8B:44:03:11:04:FC")
                 .isEqualTo(ERROR_PARAMETER);
         // Out of range Month of Year
-        assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:97:12:10:12:45:90:25:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Hour
-        assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30")
+        assertMessageValidity("04:99:0C:08:24:05:04:30:00:00:C4:C2:11:D8:75:30")
                 .isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Minute
-        assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8")
+        assertMessageValidity("04:97:15:09:00:60:00:45:04:82:09:C8:72:C8")
                 .isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Duration Hours
-        assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A")
+        assertMessageValidity("04:99:1E:07:18:32:9A:40:01:01:8B:5E:39:5A")
                 .isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Minute
-        assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC")
+        assertMessageValidity("04:97:05:0C:06:10:25:60:40:19:8B:44:03:11:04:FC")
                 .isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:99:12:06:12:45:90:25:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("04:97:0C:08:15:05:04:1E:21:00:C4:C2:11:D8:75:30")
+        assertMessageValidity("04:97:0C:08:15:05:04:1E:A1:00:C4:C2:11:D8:75:30")
                 .isEqualTo(ERROR_PARAMETER);
 
         // Invalid Digital Broadcast System
-        assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A")
+        assertMessageValidity("04:99:1E:07:18:32:80:40:01:04:8B:5E:39:5A")
                 .isEqualTo(ERROR_PARAMETER);
         // Invalid Digital Broadcast System
-        assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC")
+        assertMessageValidity("04:97:05:0C:06:10:25:59:40:93:8B:44:03:11:04:FC")
                 .isEqualTo(ERROR_PARAMETER);
         // Insufficient data for ARIB Broadcast system
-        assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75")
+        assertMessageValidity("04:99:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75")
                 .isEqualTo(ERROR_PARAMETER);
         // Insufficient data for ATSC Broadcast system
-        assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:97:1E:07:18:32:80:40:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER);
         // Insufficient data for DVB Broadcast system
-        assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04")
+        assertMessageValidity("04:99:05:0C:06:10:25:59:40:19:8B:44:03:11:04")
                 .isEqualTo(ERROR_PARAMETER);
         // Insufficient data for 2 part channel number
-        assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:97:15:09:00:15:00:45:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER);
         // Invalid Channel Number format
-        assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:99:12:06:12:45:90:25:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER);
     }
 
     @Test
     public void isValid_setExternalTimer_clearExternalTimer() {
-        assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK);
-        assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK);
+        assertMessageValidity("40:A1:0C:08:21:05:04:30:02:04:20").isEqualTo(OK);
+        assertMessageValidity("40:A2:14:09:18:40:75:25:10:05:10:00").isEqualTo(OK);
 
-        assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION);
-        assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE);
-        assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("4F:A1:0C:08:21:05:04:30:02:04:20").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F4:A2:14:09:18:40:75:25:10:05:10:00").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:A1:0C:08:21:05:04:30:02:04").isEqualTo(ERROR_PARAMETER_SHORT);
         // Out of range Day of Month
-        assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:28:09:18:40:75:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
         // Out of range Month of Year
-        assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A1:0C:0F:21:05:04:30:02:04:20").isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Hour
-        assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:14:09:24:40:75:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
         // Out of range Start Time - Minute
-        assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A1:0C:08:21:60:04:30:02:04:20").isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Duration Hours
-        assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:14:09:18:40:9A:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
         // Out of range Duration - Minute
-        assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A1:0C:08:21:05:04:60:02:04:20").isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:14:09:18:40:75:25:84:05:10:00").isEqualTo(ERROR_PARAMETER);
         // Invalid Recording Sequence
-        assertMessageValidity("40:A1:0C:08:15:05:04:1E:14:04:20").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A1:0C:08:15:05:04:1E:94:04:20").isEqualTo(ERROR_PARAMETER);
         // Invalid external source specifier
-        assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:14:09:18:40:75:25:10:08:10:00").isEqualTo(ERROR_PARAMETER);
         // Invalid External PLug
-        assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("04:A1:0C:08:21:05:04:30:02:04:00").isEqualTo(ERROR_PARAMETER);
         // Invalid Physical Address
-        assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:10").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:A2:14:09:18:40:75:25:10:05:10:10").isEqualTo(ERROR_PARAMETER);
     }
 
     @Test
@@ -392,9 +395,9 @@
         // Non programmed - Invalid not programmed error info
         assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER);
         // Programmed - Might not be enough space available - Invalid duration hours
-        assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:35:BB:9A:28").isEqualTo(ERROR_PARAMETER);
         // Not programmed - Duplicate - Invalid duration minutes
-        assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:35:EE:82:60").isEqualTo(ERROR_PARAMETER);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 3d68849..dddab65 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -108,6 +108,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -165,6 +166,7 @@
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SimpleClock;
 import android.os.SystemClock;
@@ -197,6 +199,7 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
 import com.android.internal.util.test.FsUtil;
@@ -2310,6 +2313,70 @@
         assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
     }
 
+    @SuppressWarnings("GuardedBy") // For not holding mUidRulesFirstLock
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_NEVER_APPLY_RULES_TO_CORE_UIDS)
+    public void testRulesNeverAppliedToCoreUids() throws Exception {
+        clearInvocations(mNetworkManager);
+
+        final int coreAppId = Process.FIRST_APPLICATION_UID - 102;
+        final int coreUid = UserHandle.getUid(USER_ID, coreAppId);
+
+        // Enable all restrictions and add this core uid to all allowlists.
+        mService.mDeviceIdleMode = true;
+        mService.mRestrictPower = true;
+        setRestrictBackground(true);
+        expectHasUseRestrictedNetworksPermission(coreUid, true);
+        enableRestrictedMode(true);
+        final NetworkPolicyManagerInternal internal = LocalServices.getService(
+                NetworkPolicyManagerInternal.class);
+        internal.setLowPowerStandbyActive(true);
+        internal.setLowPowerStandbyAllowlist(new int[]{coreUid});
+        internal.onTempPowerSaveWhitelistChange(coreAppId, true, REASON_OTHER, "testing");
+
+        when(mPowerExemptionManager.getAllowListedAppIds(anyBoolean()))
+                .thenReturn(new int[]{coreAppId});
+        mPowerAllowlistReceiver.onReceive(mServiceContext, null);
+
+        // A normal uid would undergo a rule change from denied to allowed on all chains, but we
+        // should not request any rule change for this core uid.
+        verify(mNetworkManager, never()).setFirewallUidRule(anyInt(), eq(coreUid), anyInt());
+        verify(mNetworkManager, never()).setFirewallUidRules(anyInt(),
+                argThat(ar -> ArrayUtils.contains(ar, coreUid)), any(int[].class));
+    }
+
+    @SuppressWarnings("GuardedBy") // For not holding mUidRulesFirstLock
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_NEVER_APPLY_RULES_TO_CORE_UIDS)
+    public void testRulesNeverAppliedToUidsWithoutInternetPermission() throws Exception {
+        clearInvocations(mNetworkManager);
+
+        mService.mInternetPermissionMap.clear();
+        expectHasInternetPermission(UID_A, false);
+
+        // Enable all restrictions and add this uid to all allowlists.
+        mService.mDeviceIdleMode = true;
+        mService.mRestrictPower = true;
+        setRestrictBackground(true);
+        expectHasUseRestrictedNetworksPermission(UID_A, true);
+        enableRestrictedMode(true);
+        final NetworkPolicyManagerInternal internal = LocalServices.getService(
+                NetworkPolicyManagerInternal.class);
+        internal.setLowPowerStandbyActive(true);
+        internal.setLowPowerStandbyAllowlist(new int[]{UID_A});
+        internal.onTempPowerSaveWhitelistChange(APP_ID_A, true, REASON_OTHER, "testing");
+
+        when(mPowerExemptionManager.getAllowListedAppIds(anyBoolean()))
+                .thenReturn(new int[]{APP_ID_A});
+        mPowerAllowlistReceiver.onReceive(mServiceContext, null);
+
+        // A normal uid would undergo a rule change from denied to allowed on all chains, but we
+        // should not request any rule this uid without the INTERNET permission.
+        verify(mNetworkManager, never()).setFirewallUidRule(anyInt(), eq(UID_A), anyInt());
+        verify(mNetworkManager, never()).setFirewallUidRules(anyInt(),
+                argThat(ar -> ArrayUtils.contains(ar, UID_A)), any(int[].class));
+    }
+
     private boolean isUidState(int uid, int procState, int procStateSeq, int capability) {
         final NetworkPolicyManager.UidState uidState = mService.getUidStateForTest(uid);
         if (uidState == null) {
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 6e84543..6ceb763 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.app.usage"
-        }
-      ]
+      "name": "FrameworksCoreTests_usage"
     },
     {
       "name": "FrameworksServicesTests",
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 5976657..71f3033 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -47,6 +47,10 @@
     compile_dex: true,
     default_to_stubs: true,
     dist_group: "android",
+
+    // This module cannot generate stubs from the api signature files as stubs depends on the
+    // private APIs, which are not visible in the api signature files.
+    build_from_text_stub: false,
 }
 
 java_library {
diff --git a/tools/systemfeatures/Android.bp b/tools/systemfeatures/Android.bp
new file mode 100644
index 0000000..2cebfe9
--- /dev/null
+++ b/tools/systemfeatures/Android.bp
@@ -0,0 +1,63 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_library_host {
+    name: "systemfeatures-gen-lib",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    static_libs: [
+        "guava",
+        "javapoet",
+    ],
+}
+
+java_binary_host {
+    name: "systemfeatures-gen-tool",
+    main_class: "com.android.systemfeatures.SystemFeaturesGenerator",
+    static_libs: ["systemfeatures-gen-lib"],
+}
+
+// TODO(b/203143243): Add golden diff test for generated sources.
+// Functional runtime behavior is covered in systemfeatures-gen-tests.
+genrule {
+    name: "systemfeatures-gen-tests-srcs",
+    cmd: "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwNoFeatures --readonly=false > $(location RwNoFeatures.java) && " +
+        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoNoFeatures --readonly=true > $(location RoNoFeatures.java) && " +
+        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwFeatures --readonly=false --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: > $(location RwFeatures.java) && " +
+        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoFeatures --readonly=true --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: > $(location RoFeatures.java)",
+    out: [
+        "RwNoFeatures.java",
+        "RoNoFeatures.java",
+        "RwFeatures.java",
+        "RoFeatures.java",
+    ],
+    tools: ["systemfeatures-gen-tool"],
+}
+
+java_test_host {
+    name: "systemfeatures-gen-tests",
+    test_suites: ["general-tests"],
+    srcs: [
+        "tests/**/*.java",
+        ":systemfeatures-gen-tests-srcs",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    static_libs: [
+        "aconfig-annotations-lib",
+        "framework-annotations-lib",
+        "junit",
+        "objenesis",
+        "mockito",
+        "truth",
+    ],
+}
diff --git a/tools/systemfeatures/OWNERS b/tools/systemfeatures/OWNERS
new file mode 100644
index 0000000..66c8506
--- /dev/null
+++ b/tools/systemfeatures/OWNERS
@@ -0,0 +1 @@
+include /PERFORMANCE_OWNERS
diff --git a/tools/systemfeatures/README.md b/tools/systemfeatures/README.md
new file mode 100644
index 0000000..5836f81
--- /dev/null
+++ b/tools/systemfeatures/README.md
@@ -0,0 +1,11 @@
+# Build-time system feature support
+
+## Overview
+
+System features exposed from `PackageManager` are defined and aggregated as
+`<feature>` xml attributes across various partitions, and are currently queried
+at runtime through the framework. This directory contains tooling that will
+support *build-time* queries of select system features, enabling optimizations
+like code stripping and conditionally dependencies when so configured.
+
+### TODO(b/203143243): Expand readme after landing codegen.
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
new file mode 100644
index 0000000..9bfda45
--- /dev/null
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemfeatures
+
+import com.google.common.base.CaseFormat
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.JavaFile
+import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.TypeSpec
+import javax.lang.model.element.Modifier
+
+/*
+ * Simple Java code generator that takes as input a list of defined features and generates an
+ * accessory class based on the provided versions.
+ *
+ * <p>Example:
+ *
+ * <pre>
+ *   <cmd> com.foo.RoSystemFeatures --readonly=true \
+ *           --feature=WATCH:0 --feature=AUTOMOTIVE: --feature=VULKAN:9348
+ * </pre>
+ *
+ * This generates a class that has the following signature:
+ *
+ * <pre>
+ * package com.foo;
+ * public final class RoSystemFeatures {
+ *     @AssumeTrueForR8
+ *     public static boolean hasFeatureWatch(Context context);
+ *     @AssumeFalseForR8
+ *     public static boolean hasFeatureAutomotive(Context context);
+ *     @AssumeTrueForR8
+ *     public static boolean hasFeatureVulkan(Context context);
+ *     public static Boolean maybeHasFeature(String feature, int version);
+ * }
+ * </pre>
+ */
+object SystemFeaturesGenerator {
+    private const val FEATURE_ARG = "--feature="
+    private const val READONLY_ARG = "--readonly="
+    private val PACKAGEMANAGER_CLASS = ClassName.get("android.content.pm", "PackageManager")
+    private val CONTEXT_CLASS = ClassName.get("android.content", "Context")
+    private val ASSUME_TRUE_CLASS =
+        ClassName.get("com.android.aconfig.annotations", "AssumeTrueForR8")
+    private val ASSUME_FALSE_CLASS =
+        ClassName.get("com.android.aconfig.annotations", "AssumeFalseForR8")
+
+    private fun usage() {
+        println("Usage: SystemFeaturesGenerator <outputClassName> [options]")
+        println(" Options:")
+        println("  --readonly=true|false    Whether to encode features as build-time constants")
+        println("  --feature=\$NAME:\$VER   A feature+version pair (blank version == disabled)")
+    }
+
+    /** Main entrypoint for build-time system feature codegen. */
+    @JvmStatic
+    fun main(args: Array<String>) {
+        if (args.size < 1) {
+            usage()
+            return
+        }
+
+        var readonly = false
+        var outputClassName: ClassName? = null
+        val features = mutableListOf<FeatureInfo>()
+        for (arg in args) {
+            when {
+                arg.startsWith(READONLY_ARG) ->
+                    readonly = arg.substring(READONLY_ARG.length).toBoolean()
+                arg.startsWith(FEATURE_ARG) -> {
+                    features.add(parseFeatureArg(arg))
+                }
+                else -> outputClassName = ClassName.bestGuess(arg)
+            }
+        }
+
+        outputClassName
+            ?: run {
+                println("Output class name must be provided.")
+                usage()
+                return
+            }
+
+        val classBuilder =
+            TypeSpec.classBuilder(outputClassName)
+                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+                .addJavadoc("@hide")
+
+        addFeatureMethodsToClass(classBuilder, readonly, features)
+        addMaybeFeatureMethodToClass(classBuilder, readonly, features)
+
+        // TODO(b/203143243): Add validation of build vs runtime values to ensure consistency.
+        JavaFile.builder(outputClassName.packageName(), classBuilder.build())
+            .build()
+            .writeTo(System.out)
+    }
+
+    /*
+     * Parses a feature argument of the form "--feature=$NAME:$VER", where "$VER" is optional.
+     *   * "--feature=WATCH:0" -> Feature enabled w/ version 0 (default version when enabled)
+     *   * "--feature=WATCH:7" -> Feature enabled w/ version 7
+     *   * "--feature=WATCH:"  -> Feature disabled
+     */
+    private fun parseFeatureArg(arg: String): FeatureInfo {
+        val featureArgs = arg.substring(FEATURE_ARG.length).split(":")
+        val name = featureArgs[0].let { if (!it.startsWith("FEATURE_")) "FEATURE_$it" else it }
+        val version = featureArgs.getOrNull(1)?.toIntOrNull()
+        return FeatureInfo(name, version)
+    }
+
+    /*
+     * Adds per-feature query methods to the class with the form:
+     * {@code public static boolean hasFeatureX(Context context)},
+     * returning the fallback value from PackageManager if not readonly.
+     */
+    private fun addFeatureMethodsToClass(
+        builder: TypeSpec.Builder,
+        readonly: Boolean,
+        features: List<FeatureInfo>
+    ) {
+        for (feature in features) {
+            // Turn "FEATURE_FOO" into "hasFeatureFoo".
+            val methodName =
+                "has" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, feature.name)
+            val methodBuilder =
+                MethodSpec.methodBuilder(methodName)
+                    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+                    .returns(Boolean::class.java)
+                    .addParameter(CONTEXT_CLASS, "context")
+
+            if (readonly) {
+                val featureEnabled = compareValues(feature.version, 0) >= 0
+                methodBuilder.addAnnotation(
+                    if (featureEnabled) ASSUME_TRUE_CLASS else ASSUME_FALSE_CLASS
+                )
+                methodBuilder.addStatement("return $featureEnabled")
+            } else {
+                methodBuilder.addStatement(
+                    "return hasFeatureFallback(context, \$T.\$N)",
+                    PACKAGEMANAGER_CLASS,
+                    feature.name
+                )
+            }
+            builder.addMethod(methodBuilder.build())
+        }
+
+        if (!readonly) {
+            builder.addMethod(
+                MethodSpec.methodBuilder("hasFeatureFallback")
+                    .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
+                    .returns(Boolean::class.java)
+                    .addParameter(CONTEXT_CLASS, "context")
+                    .addParameter(String::class.java, "featureName")
+                    .addStatement(
+                        "return context.getPackageManager().hasSystemFeature(featureName, 0)"
+                    )
+                    .build()
+            )
+        }
+    }
+
+    /*
+     * Adds a generic query method to the class with the form: {@code public static boolean
+     * maybeHasFeature(String featureName, int version)}, returning null if the feature version is
+     * undefined or not readonly.
+     *
+     * This method is useful for internal usage within the framework, e.g., from the implementation
+     * of {@link android.content.pm.PackageManager#hasSystemFeature(Context)}, when we may only
+     * want a valid result if it's defined as readonly, and we want a custom fallback otherwise
+     * (e.g., to the existing runtime binder query).
+     */
+    private fun addMaybeFeatureMethodToClass(
+        builder: TypeSpec.Builder,
+        readonly: Boolean,
+        features: List<FeatureInfo>
+    ) {
+        val methodBuilder =
+            MethodSpec.methodBuilder("maybeHasFeature")
+                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+                .addAnnotation(ClassName.get("android.annotation", "Nullable"))
+                .returns(Boolean::class.javaObjectType) // Use object type for nullability
+                .addParameter(String::class.java, "featureName")
+                .addParameter(Int::class.java, "version")
+
+        if (readonly) {
+            methodBuilder.beginControlFlow("switch (featureName)")
+            for (feature in features) {
+                methodBuilder.addCode("case \$T.\$N: ", PACKAGEMANAGER_CLASS, feature.name)
+                if (feature.version != null) {
+                    methodBuilder.addStatement("return \$L >= version", feature.version)
+                } else {
+                    methodBuilder.addStatement("return false")
+                }
+            }
+            methodBuilder.addCode("default: ")
+            methodBuilder.addStatement("break")
+            methodBuilder.endControlFlow()
+        }
+        methodBuilder.addStatement("return null")
+        builder.addMethod(methodBuilder.build())
+    }
+
+    private data class FeatureInfo(val name: String, val version: Int?)
+}
diff --git a/tools/systemfeatures/tests/Context.java b/tools/systemfeatures/tests/Context.java
new file mode 100644
index 0000000..630bc07
--- /dev/null
+++ b/tools/systemfeatures/tests/Context.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.content.pm.PackageManager;
+
+/** Stub for testing. */
+public class Context {
+    /** @hide */
+    public PackageManager getPackageManager() {
+        return null;
+    }
+}
diff --git a/tools/systemfeatures/tests/PackageManager.java b/tools/systemfeatures/tests/PackageManager.java
new file mode 100644
index 0000000..645d500
--- /dev/null
+++ b/tools/systemfeatures/tests/PackageManager.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+/** Stub for testing */
+public class PackageManager {
+    public static final String FEATURE_AUTO = "automotive";
+    public static final String FEATURE_VULKAN = "vulkan";
+    public static final String FEATURE_WATCH = "watch";
+    public static final String FEATURE_WIFI = "wifi";
+
+    /** @hide */
+    public boolean hasSystemFeature(String featureName, int version) {
+        return false;
+    }
+}
diff --git a/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java b/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
new file mode 100644
index 0000000..547d2cb
--- /dev/null
+++ b/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemfeatures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(JUnit4.class)
+public class SystemFeaturesGeneratorTest {
+
+    @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+
+    @Mock private Context mContext;
+    @Mock private PackageManager mPackageManager;
+
+    @Before
+    public void setUp() {
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+    }
+
+    @Test
+    public void testReadonlyDisabledNoDefinedFeatures() {
+        // Always report null for conditional queries if readonly codegen is disabled.
+        assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isNull();
+        assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isNull();
+        assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
+        assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
+        assertThat(RwNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+    }
+
+    @Test
+    public void testReadonlyNoDefinedFeatures() {
+        // If no features are explicitly declared as readonly available, always report
+        // null for conditional queries.
+        assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isNull();
+        assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isNull();
+        assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
+        assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
+        assertThat(RoNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+    }
+
+    @Test
+    public void testReadonlyDisabledWithDefinedFeatures() {
+        // Always fall back to the PackageManager for defined, explicit features queries.
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(true);
+        assertThat(RwFeatures.hasFeatureWatch(mContext)).isTrue();
+
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(false);
+        assertThat(RwFeatures.hasFeatureWatch(mContext)).isFalse();
+
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI, 0)).thenReturn(true);
+        assertThat(RwFeatures.hasFeatureWifi(mContext)).isTrue();
+
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN, 0)).thenReturn(false);
+        assertThat(RwFeatures.hasFeatureVulkan(mContext)).isFalse();
+
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(false);
+        assertThat(RwFeatures.hasFeatureAuto(mContext)).isFalse();
+
+        // For defined and undefined features, conditional queries should report null (unknown).
+        assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isNull();
+        assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isNull();
+        assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
+        assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
+        assertThat(RwFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+    }
+
+    @Test
+    public void testReadonlyWithDefinedFeatures() {
+        // Always use the build-time feature version for defined, explicit feature queries, never
+        // falling back to the runtime query.
+        assertThat(RoFeatures.hasFeatureWatch(mContext)).isTrue();
+        assertThat(RoFeatures.hasFeatureWifi(mContext)).isTrue();
+        assertThat(RoFeatures.hasFeatureVulkan(mContext)).isFalse();
+        assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
+        verify(mPackageManager, never()).hasSystemFeature(anyString(), anyInt());
+
+        // For defined feature types, conditional queries should reflect the build-time versions.
+        // VERSION=1
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, -1)).isTrue();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isTrue();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 100)).isFalse();
+
+        // VERSION=0
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, -1)).isTrue();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isTrue();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 100)).isFalse();
+
+        // VERSION=-1
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, -1)).isTrue();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isFalse();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 100)).isFalse();
+
+        // DISABLED
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isFalse();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isFalse();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isFalse();
+
+        // For undefined types, conditional queries should report null (unknown).
+        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", -1)).isNull();
+        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 100)).isNull();
+    }
+}