Merge "Do not start fingerprint HAL if it is unstartable" into main
diff --git a/Android.bp b/Android.bp
index 68fc474..e688bff 100644
--- a/Android.bp
+++ b/Android.bp
@@ -261,7 +261,6 @@
         "devicepolicyprotosnano",
         "ImmutabilityAnnotation",
 
-        "com.android.sysprop.init",
         "com.android.sysprop.localization",
         "PlatformProperties",
     ],
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/core/src/android/libcore/SystemArrayCopyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java
index 6363e9c..25e4c43 100644
--- a/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java
@@ -16,7 +16,8 @@
 
 package android.libcore;
 
-import android.perftests.utils.BenchmarkState;
+import androidx.benchmark.BenchmarkState;
+import androidx.benchmark.junit4.BenchmarkRule;
 import android.perftests.utils.PerfStatusReporter;
 
 import androidx.test.filters.LargeTest;
@@ -34,7 +35,8 @@
 @RunWith(JUnitParamsRunner.class)
 @LargeTest
 public class SystemArrayCopyPerfTest {
-    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+    @Rule
+    public BenchmarkRule mBenchmarkRule = new BenchmarkRule();
 
     public static Collection<Object[]> getData() {
         return Arrays.asList(
@@ -51,7 +53,7 @@
         final int len = arrayLength;
         char[] src = new char[len];
         char[] dst = new char[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -63,7 +65,7 @@
         final int len = arrayLength;
         byte[] src = new byte[len];
         byte[] dst = new byte[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -75,7 +77,7 @@
         final int len = arrayLength;
         short[] src = new short[len];
         short[] dst = new short[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -87,7 +89,7 @@
         final int len = arrayLength;
         int[] src = new int[len];
         int[] dst = new int[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -99,7 +101,7 @@
         final int len = arrayLength;
         long[] src = new long[len];
         long[] dst = new long[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -111,7 +113,7 @@
         final int len = arrayLength;
         float[] src = new float[len];
         float[] dst = new float[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -123,7 +125,7 @@
         final int len = arrayLength;
         double[] src = new double[len];
         double[] dst = new double[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
@@ -135,7 +137,7 @@
         final int len = arrayLength;
         boolean[] src = new boolean[len];
         boolean[] dst = new boolean[len];
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
             System.arraycopy(src, 0, dst, 0, len);
         }
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index 856dba3..9eea712 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -45,3 +45,8 @@
         "trace_configs/trace_config_multi_user.textproto",
     ],
 }
+
+prebuilt_etc {
+    name: "trace_config_multi_user.textproto",
+    src: ":multi_user_trace_config",
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 11d3e96..a21d810c 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -2628,8 +2628,13 @@
             for (int i=0; i<allowPowerExceptIdle.size(); i++) {
                 String pkg = allowPowerExceptIdle.valueAt(i);
                 try {
+                    // On some devices (eg. HSUM), some apps may
+                    // be not be pre-installed on user 0, but may be
+                    // pre-installed on FULL users. Look for pre-installed system
+                    // apps across all users to make sure they're properly
+                    // allowlisted.
                     ApplicationInfo ai = pm.getApplicationInfo(pkg,
-                            PackageManager.MATCH_SYSTEM_ONLY);
+                            PackageManager.MATCH_ANY_USER | PackageManager.MATCH_SYSTEM_ONLY);
                     int appid = UserHandle.getAppId(ai.uid);
                     mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
                     mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
@@ -2640,8 +2645,13 @@
             for (int i=0; i<allowPower.size(); i++) {
                 String pkg = allowPower.valueAt(i);
                 try {
+                    // On some devices (eg. HSUM), some apps may
+                    // be not be pre-installed on user 0, but may be
+                    // pre-installed on FULL users. Look for pre-installed system
+                    // apps across all users to make sure they're properly
+                    // allowlisted.
                     ApplicationInfo ai = pm.getApplicationInfo(pkg,
-                            PackageManager.MATCH_SYSTEM_ONLY);
+                            PackageManager.MATCH_ANY_USER | PackageManager.MATCH_SYSTEM_ONLY);
                     int appid = UserHandle.getAppId(ai.uid);
                     // These apps are on both the whitelist-except-idle as well
                     // as the full whitelist, so they apply in all cases.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
index e82df12..36b6c80 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
@@ -16,12 +16,7 @@
             ]
         },
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {"include-filter": "com.android.server.job"},
-                {"exclude-annotation": "androidx.test.filters.FlakyTest"},
-                {"exclude-annotation": "androidx.test.filters.LargeTest"}
-            ]
+            "name": "FrameworksServicesTests_com_android_server_job_Presubmit"
         }
     ],
     "postsubmit": [
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index a75415e..52670a2 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -17,11 +17,7 @@
       ]
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {"include-filter": "com.android.server.usage"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
-      ]
+      "name": "FrameworksServicesTests_com_android_server_usage_Presubmit"
     }
   ],
   "postsubmit": [
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/api/system-current.txt b/core/api/system-current.txt
index 02c88e2..ccae2ba 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11883,6 +11883,7 @@
     field public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION = "android.settings.MANAGE_APP_OVERLAY_PERMISSION";
     field public static final String ACTION_MANAGE_DOMAIN_URLS = "android.settings.MANAGE_DOMAIN_URLS";
     field public static final String ACTION_MANAGE_MORE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_MORE_DEFAULT_APPS_SETTINGS";
+    field @FlaggedApi("android.nfc.nfc_action_manage_services_settings") public static final String ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS = "android.settings.MANAGE_OTHER_NFC_SERVICES_SETTINGS";
     field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS = "android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS";
     field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
     field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index a29c196..5f618f6 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -29,12 +29,7 @@
         },
         {
             "file_patterns": ["(/|^)AppOpsManager.java"],
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.appop"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_appop"
         },
         {
             "file_patterns": ["(/|^)AppOpsManager.java"],
@@ -153,18 +148,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 +161,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..ce8a580 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": [
@@ -86,10 +82,7 @@
         "PowerComponents\\.java",
         "[^/]*BatteryConsumer[^/]*\\.java"
       ],
-      "name": "FrameworksServicesTests",
-      "options": [
-        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }
-      ]
+      "name": "FrameworksServicesTests_battery_stats"
     },
     {
       "file_patterns": [
@@ -132,12 +125,7 @@
     },
     {
       "file_patterns": ["Environment[^/]*\\.java"],
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.os.EnvironmentTest"
-        }
-      ]
+      "name": "FrameworksCoreTests_environment"
     }
   ],
   "postsubmit": [
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 51585af..beeab14 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2256,6 +2256,26 @@
             "android.settings.MANAGE_MORE_DEFAULT_APPS_SETTINGS";
 
     /**
+     * Activity Action: Show Other NFC services settings.
+     * <p>
+     * If a Settings activity handles this intent action, an "Other NFC services" entry will be
+     * shown in the Default payment app settings, and clicking it will launch that activity.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_ACTION_MANAGE_SERVICES_SETTINGS)
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @SystemApi
+    public static final String ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS =
+            "android.settings.MANAGE_OTHER_NFC_SERVICES_SETTINGS";
+
+    /**
      * Activity Action: Show app screen size list settings for user to override app aspect
      * ratio.
      * <p>
diff --git a/core/java/android/security/advancedprotection/OWNERS b/core/java/android/security/advancedprotection/OWNERS
new file mode 100644
index 0000000..ddac8ed
--- /dev/null
+++ b/core/java/android/security/advancedprotection/OWNERS
@@ -0,0 +1,12 @@
+# Bug component: 315013
+
+achim@google.com
+azharaa@google.com
+cpinelli@google.com
+eranm@google.com
+hanikazmi@google.com
+haok@google.com
+lus@google.com
+mattgilbride@google.com
+mpgroover@google.com
+wnan@google.com
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/contentprotection/OWNERS b/core/java/android/view/contentprotection/OWNERS
index b3583a7..48052c6 100644
--- a/core/java/android/view/contentprotection/OWNERS
+++ b/core/java/android/view/contentprotection/OWNERS
@@ -1,4 +1,6 @@
-# Bug component: 544200
+# Bug component: 1040349
 
-include /core/java/android/view/contentcapture/OWNERS
+njagar@google.com
+williamluh@google.com
+aaronjosephs@google.com
 
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..c31ec4a 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": [
@@ -36,10 +28,7 @@
         "Kernel[^/]*\\.java",
         "[^/]*Power[^/]*\\.java"
       ],
-      "name": "FrameworksServicesTests",
-      "options": [
-        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }
-      ]
+      "name": "FrameworksServicesTests_battery_stats"
     },
     {
       "file_patterns": [
@@ -50,25 +39,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/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 84ca1ba..7a4670f4 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -53,7 +53,7 @@
 }
 
 struct SecurityContext_Delete {
-    void operator()(security_context_t p) const {
+    void operator()(char* p) const {
         freecon(p);
     }
 };
@@ -111,7 +111,7 @@
         return NULL;
     }
 
-    security_context_t tmp = NULL;
+    char* tmp = NULL;
     if (selabel_lookup(selabel_handle, &tmp, path_c_str, S_IFREG) != 0) {
       ALOGE("fileSelabelLookup => selabel_lookup for %s failed: %d", path_c_str, errno);
       return NULL;
@@ -138,7 +138,7 @@
         return NULL;
     }
 
-    security_context_t tmp = NULL;
+    char* tmp = NULL;
     int ret;
     if (isSocket) {
         ret = getpeercon(fd, &tmp);
@@ -184,7 +184,7 @@
  * Function: setFSCreateCon
  * Purpose: set security context used for creating a new file system object
  * Parameters:
- *       context: security_context_t representing the new context of a file system object,
+ *       context: char* representing the new context of a file system object,
  *                set to NULL to return to the default policy behavior
  * Returns: true on success, false on error
  * Exception: none
@@ -267,7 +267,7 @@
         return NULL;
     }
 
-    security_context_t tmp = NULL;
+    char* tmp = NULL;
     int ret = getfilecon(path.c_str(), &tmp);
     Unique_SecurityContext context(tmp);
 
@@ -293,7 +293,7 @@
         return NULL;
     }
 
-    security_context_t tmp = NULL;
+    char* tmp = NULL;
     int ret = getcon(&tmp);
     Unique_SecurityContext context(tmp);
 
@@ -320,7 +320,7 @@
         return NULL;
     }
 
-    security_context_t tmp = NULL;
+    char* tmp = NULL;
     int ret = getpidcon(static_cast<pid_t>(pid), &tmp);
     Unique_SecurityContext context(tmp);
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index dbbcbad..f1c1d92 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -19,14 +19,6 @@
 
 #include "com_android_internal_os_Zygote.h"
 
-#include <async_safe/log.h>
-
-// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <sys/types.h>
-#include <dirent.h>
-
 #include <algorithm>
 #include <array>
 #include <atomic>
@@ -41,32 +33,31 @@
 
 #include <android/fdsan.h>
 #include <arpa/inet.h>
+#include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <mntent.h>
-#include <paths.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/auxv.h>
 #include <sys/capability.h>
-#include <sys/cdefs.h>
 #include <sys/eventfd.h>
+#include <sys/mount.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
 #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>
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.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/OWNERS b/core/tests/coretests/src/android/view/contentprotection/OWNERS
index b3583a7..3d09da3 100644
--- a/core/tests/coretests/src/android/view/contentprotection/OWNERS
+++ b/core/tests/coretests/src/android/view/contentprotection/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 544200
+# Bug component: 1040349
 
-include /core/java/android/view/contentcapture/OWNERS
+include /core/java/android/view/contentprotection/OWNERS
 
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/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
index 94519a0..055b355 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -134,7 +134,6 @@
                 t.clear();
                 mMainExecutor.execute(() -> {
                     finishCallback.onTransitionFinished(wct);
-                    mRemote = null;
                 });
             }
         };
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 888105d..5aef520 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -667,7 +667,11 @@
                 Log.e(TAG, "Got duplicate transitionReady for " + transitionToken);
                 // The transition is already somewhere else in the pipeline, so just return here.
                 t.apply();
-                existing.mFinishT.merge(finishT);
+                if (existing.mFinishT != null) {
+                    existing.mFinishT.merge(finishT);
+                } else {
+                    existing.mFinishT = finishT;
+                }
                 return;
             }
             // This usually means the system is in a bad state and may not recover; however,
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/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
index 8ddc572..49ee8f7 100644
--- a/libs/androidfw/PosixUtils.cpp
+++ b/libs/androidfw/PosixUtils.cpp
@@ -119,7 +119,7 @@
       auto err = ReadFile(stderr[0]);
       result.stderr_str = err ? std::move(*err) : "";
       close(stderr[0]);
-      return std::move(result);
+      return result;
   }
 }
 
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index e604cb7..82e6ed3 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -91,7 +91,7 @@
     private static final Object sMainTvViewLock = new Object();
     private static WeakReference<TvView> sMainTvView = NULL_TV_VIEW;
 
-    private final Handler mHandler = new Handler();
+    private Handler mHandler = new Handler();
     private Session mSession;
     private SurfaceView mSurfaceView;
     private Surface mSurface;
@@ -207,6 +207,17 @@
         mCallback = callback;
     }
 
+    /**
+     * Sets the handler to be invoked when an event is dispatched to this TvView.
+     * If handler is not set by this function, TvView will use its default handler.
+     *
+     * @param handler The handler to handle events.
+     * @hide
+     */
+    public void setHandler(@NonNull Handler handler) {
+        mHandler = handler;
+    }
+
     /** @hide */
     public Session getInputSession() {
         return mSession;
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index 060abfd..ffbf0a8 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -62,7 +62,7 @@
             std::shared_ptr<C2Buffer> buffer =
                 C2Buffer::CreateLinearBuffer(block.subBlock(offset, size));
             for (const std::shared_ptr<const C2Info> &info : mBuffer->info()) {
-                std::shared_ptr<C2Param> param = std::move(C2Param::Copy(*info));
+                std::shared_ptr<C2Param> param = C2Param::Copy(*info);
                 buffer->setInfo(std::static_pointer_cast<C2Info>(param));
             }
             return buffer;
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index cf7aea4..447e980 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -220,11 +220,14 @@
     field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
     field public static final String CATEGORY_OTHER = "other";
     field public static final String CATEGORY_PAYMENT = "payment";
+    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String DH = "DH";
+    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String ESE = "ESE";
     field public static final String EXTRA_CATEGORY = "category";
     field public static final String EXTRA_SERVICE_COMPONENT = "component";
     field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
     field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
     field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
+    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String UICC = "UICC";
   }
 
   public abstract class HostApduService extends android.app.Service {
@@ -232,6 +235,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/api/system-current.txt b/nfc/api/system-current.txt
index 3375e18c..2ff9829 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -57,6 +57,7 @@
 
   @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension {
     method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference();
+    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList();
     method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate();
     method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback);
     method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
@@ -74,6 +75,8 @@
   public final class CardEmulation {
     method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
+    method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, @Nullable String, @Nullable String);
+    method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity);
   }
 
 }
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index 90ca92f..6c0f933 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);
@@ -113,4 +113,5 @@
     void clearPreference();
     void setScreenState();
     void checkFirmware();
+    List<String> fetchActiveNfceeList();
 }
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index cb97f23..79f1275 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -48,6 +48,6 @@
     boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
     boolean isDefaultPaymentRegistered();
 
-    boolean overrideRoutingTable(int userHandle, String protocol, String technology);
-    boolean recoverRoutingTable(int userHandle);
+    void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
+    void recoverRoutingTable(int userHandle);
 }
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/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 2ec819c..204ba9f 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -26,6 +26,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Executor;
 
 /**
@@ -153,6 +155,19 @@
         NfcAdapter.callService(() -> NfcAdapter.sService.checkFirmware());
     }
 
+    /**
+     * Get the Active NFCEE (NFC Execution Environment) List
+     *
+     * @return List of activated secure elements on success
+     *         which can contain "eSE" and "UICC", otherwise empty list.
+     */
+    @NonNull
+    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+    public List<String> getActiveNfceeList() {
+        return NfcAdapter.callServiceReturn(() ->
+            NfcAdapter.sService.fetchActiveNfceeList(), new ArrayList<String>());
+    }
+
     private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub {
         @Override
         public void onTagConnected(boolean connected, Tag tag) throws RemoteException {
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index e0438ce..0605dbe 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.annotation.UserHandleAware;
 import android.annotation.UserIdInt;
@@ -43,6 +44,8 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
 import java.util.HexFormat;
 import java.util.List;
@@ -148,6 +151,21 @@
      *    that service will be invoked directly.
      */
     public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
+    /**
+     * Route to Device Host (DH).
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+    public static final String DH = "DH";
+    /**
+     * Route to eSE.
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+    public static final String ESE = "ESE";
+    /**
+     * Route to UICC.
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+    public static final String UICC = "UICC";
 
     static boolean sIsInitialized = false;
     static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>();
@@ -865,11 +883,22 @@
                 sService.setServiceEnabledForCategoryOther(userId, service, status), false);
     }
 
+    /** @hide */
+    @StringDef({
+        DH,
+        ESE,
+        UICC
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ProtocolAndTechnologyRoute {}
+
      /**
       * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
       * while this Activity is in the foreground.
       *
-      * The parameter set to null can be used to keep current values for that entry.
+      * The parameter set to null can be used to keep current values for that entry. Either
+      * Protocol Route or Technology Route should be override when calling this API, otherwise
+      * throw {@link IllegalArgumentException}.
       * <p>
       * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
       * <pre>
@@ -877,26 +906,40 @@
       *     mNfcAdapter.overrideRoutingTable(this , "ESE" , null);
       * }</pre>
       * </p>
-      * Also activities must call this method when it goes to the background,
-      * with all parameters set to null.
+      * Also activities must call {@link #recoverRoutingTable(Activity)}
+      * when it goes to the background. Only the package of the
+      * currently preferred service (the service set as preferred by the current foreground
+      * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the
+      * current Default Wallet Role Holder {@link android.app.role.RoleManager#ROLE_WALLET}),
+      * otherwise a call to this method will fail and throw {@link SecurityException}.
       * @param activity The Activity that requests NFC controller routing table to be changed.
       * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE".
-      * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE".
-      * @return true if operation is successful and false otherwise
-      *
+      * @param technology Tech-A, Tech-B and Tech-F route destination, which can be "DH" or "UICC"
+      * or "ESE".
+      * @throws SecurityException if the caller is not the preferred NFC service
+      * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the
+      * foreground, or both protocol route and technology route are null.
+      * <p>
       * This is a high risk API and only included to support mainline effort
       * @hide
       */
-    public boolean overrideRoutingTable(Activity activity, String protocol, String technology) {
-        if (activity == null) {
-            throw new NullPointerException("activity or service or category is null");
-        }
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+    public void overrideRoutingTable(
+            @NonNull Activity activity, @ProtocolAndTechnologyRoute @Nullable String protocol,
+            @ProtocolAndTechnologyRoute @Nullable String technology) {
         if (!activity.isResumed()) {
             throw new IllegalArgumentException("Activity must be resumed.");
         }
-        return callServiceReturn(() ->
+        if (protocol == null && technology == null) {
+            throw new IllegalArgumentException(("Both Protocol and Technology are null."));
+        }
+        callService(() ->
                 sService.overrideRoutingTable(
-                    mContext.getUser().getIdentifier(), protocol, technology), false);
+                    mContext.getUser().getIdentifier(),
+                    protocol,
+                    technology,
+                    mContext.getPackageName()));
     }
 
     /**
@@ -904,20 +947,19 @@
      * which was changed by {@link #overrideRoutingTable(Activity, String, String)}
      *
      * @param activity The Activity that requested NFC controller routing table to be changed.
-     * @return true if operation is successful and false otherwise
+     * @throws IllegalArgumentException if the caller is not in the foreground.
      *
      * @hide
      */
-    public boolean recoverRoutingTable(Activity activity) {
-        if (activity == null) {
-            throw new NullPointerException("activity is null");
-        }
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+    public void recoverRoutingTable(@NonNull Activity activity) {
         if (!activity.isResumed()) {
             throw new IllegalArgumentException("Activity must be resumed.");
         }
-        return callServiceReturn(() ->
+        callService(() ->
                 sService.recoverRoutingTable(
-                    mContext.getUser().getIdentifier()), false);
+                    mContext.getUser().getIdentifier()));
     }
 
     /**
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..468147f 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"
@@ -117,3 +125,18 @@
     bug: "321310044"
 }
 
+flag {
+    name: "nfc_action_manage_services_settings"
+    is_exported: true
+    namespace: "nfc"
+    description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS"
+    bug: "358129872"
+}
+
+flag {
+    name: "nfc_override_recover_routing_table"
+    is_exported: true
+    namespace: "nfc"
+    description: "Enable override and recover routing table"
+    bug: "329043523"
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 6a1998a..707b4e2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -45,8 +45,8 @@
 import androidx.credentials.CreateCustomCredentialRequest
 import androidx.credentials.CreatePasswordRequest
 import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.CredentialOption
 import androidx.credentials.PasswordCredential
-import androidx.credentials.PriorityHints
 import androidx.credentials.PublicKeyCredential
 import androidx.credentials.provider.CreateEntry
 import androidx.credentials.provider.RemoteEntry
@@ -175,9 +175,9 @@
                         "androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE",
                         when (option.type) {
                             PasswordCredential.TYPE_PASSWORD_CREDENTIAL ->
-                                PriorityHints.PRIORITY_PASSWORD_OR_SIMILAR
+                                CredentialOption.PRIORITY_PASSWORD_OR_SIMILAR
                             PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL -> 100
-                            else -> PriorityHints.PRIORITY_DEFAULT
+                            else -> CredentialOption.PRIORITY_DEFAULT
                         }
                 )
                 typePriorityMap[option.type] = priority
@@ -344,8 +344,8 @@
                 }
                 is CreateCustomCredentialRequest -> {
                     // TODO: directly use the display info once made public
-                    val displayInfo = CreateCredentialRequest.DisplayInfo
-                        .parseFromCredentialDataBundle(createCredentialRequest.credentialData)
+                    val displayInfo = CreateCredentialRequest.DisplayInfo.createFrom(
+                            createCredentialRequest.credentialData)
                         ?: return null
                     RequestDisplayInfo(
                         title = displayInfo.userId.toString(),
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index ef40188..bdb20c1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -18,7 +18,7 @@
 
 import android.credentials.flags.Flags.selectorUiImprovementsEnabled
 import android.graphics.drawable.Drawable
-import androidx.credentials.PriorityHints
+import androidx.credentials.CredentialOption
 import com.android.credentialmanager.model.get.ProviderInfo
 import com.android.credentialmanager.model.EntryInfo
 import com.android.credentialmanager.model.get.AuthenticationEntryInfo
@@ -214,10 +214,10 @@
         // First prefer passkey type for its security benefits
         if (p0.rawCredentialType != p1.rawCredentialType) {
             val p0Priority = typePriorityMap.getOrDefault(
-                    p0.rawCredentialType, PriorityHints.PRIORITY_DEFAULT
+                    p0.rawCredentialType, CredentialOption.PRIORITY_DEFAULT
             )
             val p1Priority = typePriorityMap.getOrDefault(
-                    p1.rawCredentialType, PriorityHints.PRIORITY_DEFAULT
+                    p1.rawCredentialType, CredentialOption.PRIORITY_DEFAULT
             )
             if (p0Priority < p1Priority) {
                 return -1
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
index d33433f..2fb32a7 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
@@ -16,10 +16,12 @@
 
 package com.android.packageinstaller;
 
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.BroadcastOptions;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.app.PendingIntent;
@@ -161,25 +163,31 @@
             return;
         }
 
+        // Allow the error handling actvities to start in the background.
+        final BroadcastOptions options = BroadcastOptions.makeBasic();
+        options.setPendingIntentBackgroundActivityStartMode(
+                MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
         switch (mStatus) {
             case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED:
                 activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */
-                        null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0);
+                        null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0,
+                        options.toBundle());
                 break;
             case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE:
                 if (mExtraIntent != null) {
                     activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */
-                            null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0);
+                            null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0,
+                            options.toBundle());
                 } else {
                     Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
-                    startActivity(intent);
+                    startActivity(intent, options.toBundle());
                 }
                 break;
             case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED:
                 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                 Uri uri = Uri.fromParts("package", mInstallerPackageName, null);
                 intent.setData(uri);
-                startActivity(intent);
+                startActivity(intent, options.toBundle());
                 break;
             default:
                 // Do nothing. The rest of the dialogs are purely informational.
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/ravenwood/tools/ravenizer-fake/Android.bp b/ravenwood/tools/ravenizer-fake/Android.bp
new file mode 100644
index 0000000..7e2c407
--- /dev/null
+++ b/ravenwood/tools/ravenizer-fake/Android.bp
@@ -0,0 +1,14 @@
+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"],
+}
+
+sh_binary_host {
+    name: "ravenizer",
+    src: "ravenizer",
+    visibility: ["//visibility:public"],
+}
diff --git a/ravenwood/tools/ravenizer-fake/ravenizer b/ravenwood/tools/ravenizer-fake/ravenizer
new file mode 100755
index 0000000..84b3c8e
--- /dev/null
+++ b/ravenwood/tools/ravenizer-fake/ravenizer
@@ -0,0 +1,31 @@
+#!/bin/bash
+# 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.
+
+# "Fake" ravenizer, which just copies the file.
+# We need it to add ravenizer support to Soong on AOSP,
+# when the actual ravenizer is not in AOSP yet.
+
+invalid_arg() {
+    echo "Ravenizer(fake): invalid args" 1>&2
+    exit 1
+}
+
+(( $# >= 4 )) || invalid_arg
+[[ "$1" == "--in-jar" ]] || invalid_arg
+[[ "$3" == "--out-jar" ]] || invalid_arg
+
+echo "Ravenizer(fake): copiyng $2 to $4"
+
+cp "$2" "$4"
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
index 299d33f..454a329 100644
--- a/services/accessibility/TEST_MAPPING
+++ b/services/accessibility/TEST_MAPPING
@@ -25,32 +25,10 @@
       ]
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.accessibility"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
+      "name": "FrameworksServicesTests_accessibility_Presubmit"
     },
     {
-      "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/contentcapture/java/com/android/server/contentprotection/OWNERS b/services/contentcapture/java/com/android/server/contentprotection/OWNERS
new file mode 100644
index 0000000..3d09da3
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentprotection/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1040349
+
+include /core/java/android/view/contentprotection/OWNERS
+
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index a627a39..f230646 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -10,9 +10,6 @@
 # Zram writeback
 per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com
 
-# Userspace reboot
-per-file UserspaceRebootLogger.java = ioffe@google.com, dvander@google.com
-
 # ServiceWatcher
 per-file ServiceWatcher.java = sooniln@google.com
 
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/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java
deleted file mode 100644
index 89327b5..0000000
--- a/services/core/java/com/android/server/UserspaceRebootLogger.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED;
-import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED;
-
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.util.FrameworkStatsLog;
-
-import java.util.concurrent.Executor;
-
-/**
- * Utility class to help abstract logging {@code UserspaceRebootReported} atom.
- */
-public final class UserspaceRebootLogger {
-
-    private static final String TAG = "UserspaceRebootLogger";
-
-    private static final String USERSPACE_REBOOT_SHOULD_LOG_PROPERTY =
-            "persist.sys.userspace_reboot.log.should_log";
-    private static final String USERSPACE_REBOOT_LAST_STARTED_PROPERTY =
-            "sys.userspace_reboot.log.last_started";
-    private static final String USERSPACE_REBOOT_LAST_FINISHED_PROPERTY =
-            "sys.userspace_reboot.log.last_finished";
-    private static final String LAST_BOOT_REASON_PROPERTY = "sys.boot.reason.last";
-
-    private UserspaceRebootLogger() {}
-
-    /**
-     * Modifies internal state to note that {@code UserspaceRebootReported} atom needs to be
-     * logged on the next successful boot.
-     *
-     * <p>This call should only be made on devices supporting userspace reboot.
-     */
-    public static void noteUserspaceRebootWasRequested() {
-        if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
-            Slog.wtf(TAG, "noteUserspaceRebootWasRequested: Userspace reboot is not supported.");
-            return;
-        }
-
-        SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, "1");
-        SystemProperties.set(USERSPACE_REBOOT_LAST_STARTED_PROPERTY,
-                String.valueOf(SystemClock.elapsedRealtime()));
-    }
-
-    /**
-     * Updates internal state on boot after successful userspace reboot.
-     *
-     * <p>Should be called right before framework sets {@code sys.boot_completed} property.
-     *
-     * <p>This call should only be made on devices supporting userspace reboot.
-     */
-    public static void noteUserspaceRebootSuccess() {
-        if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
-            Slog.wtf(TAG, "noteUserspaceRebootSuccess: Userspace reboot is not supported.");
-            return;
-        }
-
-        SystemProperties.set(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY,
-                String.valueOf(SystemClock.elapsedRealtime()));
-    }
-
-    /**
-     * Returns {@code true} if {@code UserspaceRebootReported} atom should be logged.
-     *
-     * <p>On devices that do not support userspace reboot this method will always return {@code
-     * false}.
-     */
-    public static boolean shouldLogUserspaceRebootEvent() {
-        if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
-            return false;
-        }
-
-        return SystemProperties.getBoolean(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, false);
-    }
-
-    /**
-     * Asynchronously logs {@code UserspaceRebootReported} on the given {@code executor}.
-     *
-     * <p>Should be called in the end of {@link
-     * com.android.server.am.ActivityManagerService#finishBooting()} method, after framework have
-     * tried to proactivelly unlock storage of the primary user.
-     *
-     * <p>This call should only be made on devices supporting userspace reboot.
-     */
-    public static void logEventAsync(boolean userUnlocked, Executor executor) {
-        if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
-            Slog.wtf(TAG, "logEventAsync: Userspace reboot is not supported.");
-            return;
-        }
-
-        final int outcome = computeOutcome();
-        final long durationMillis;
-        if (outcome == USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS) {
-            durationMillis = SystemProperties.getLong(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY, 0)
-                    - SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, 0);
-        } else {
-            durationMillis = 0;
-        }
-        final int encryptionState =
-                userUnlocked
-                    ? USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED
-                    : USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED;
-        executor.execute(
-                () -> {
-                    Slog.i(TAG, "Logging UserspaceRebootReported atom: { outcome: " + outcome
-                            + " durationMillis: " + durationMillis + " encryptionState: "
-                            + encryptionState + " }");
-                    FrameworkStatsLog.write(FrameworkStatsLog.USERSPACE_REBOOT_REPORTED, outcome,
-                            durationMillis, encryptionState);
-                    SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, "");
-                });
-    }
-
-    private static int computeOutcome() {
-        if (SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, -1) != -1) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS;
-        }
-        String reason = TextUtils.emptyIfNull(SystemProperties.get(LAST_BOOT_REASON_PROPERTY, ""));
-        if (reason.startsWith("reboot,")) {
-            reason = reason.substring("reboot".length());
-        }
-        if (reason.startsWith("userspace_failed,watchdog_fork")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
-        }
-        if (reason.startsWith("userspace_failed,shutdown_aborted")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
-        }
-        if (reason.startsWith("mount_userdata_failed")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
-        }
-        if (reason.startsWith("userspace_failed,init_user0")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
-        }
-        if (reason.startsWith("userspace_failed,enablefilecrypto")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
-        }
-        if (reason.startsWith("userspace_failed,watchdog_triggered")) {
-            return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED;
-        }
-        return USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN;
-    }
-}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 30b1c6f..7395c05 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -370,7 +370,6 @@
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.server.ServerProtoEnums;
-import android.sysprop.InitProperties;
 import android.system.Os;
 import android.system.OsConstants;
 import android.telephony.TelephonyManager;
@@ -455,7 +454,6 @@
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.ThreadPriorityBooster;
-import com.android.server.UserspaceRebootLogger;
 import com.android.server.Watchdog;
 import com.android.server.am.ComponentAliasResolver.Resolution;
 import com.android.server.am.LowMemDetector.MemFactor;
@@ -2373,20 +2371,6 @@
         }
     }
 
-    private void maybeLogUserspaceRebootEvent() {
-        if (!UserspaceRebootLogger.shouldLogUserspaceRebootEvent()) {
-            return;
-        }
-        final int userId = mUserController.getCurrentUserId();
-        if (userId != UserHandle.USER_SYSTEM) {
-            // Only log for user0.
-            return;
-        }
-        // TODO(b/148767783): should we check all profiles under user0?
-        UserspaceRebootLogger.logEventAsync(StorageManager.isCeStorageUnlocked(userId),
-                BackgroundThread.getExecutor());
-    }
-
     /**
      * Encapsulates global settings related to hidden API enforcement behaviour, including tracking
      * the latest value via a content observer.
@@ -5213,12 +5197,6 @@
             // Start looking for apps that are abusing wake locks.
             Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG);
             mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL);
-            // Check if we are performing userspace reboot before setting sys.boot_completed to
-            // avoid race with init reseting sys.init.userspace_reboot.in_progress once sys
-            // .boot_completed is 1.
-            if (InitProperties.userspace_reboot_in_progress().orElse(false)) {
-                UserspaceRebootLogger.noteUserspaceRebootSuccess();
-            }
             // Tell anyone interested that we are done booting!
             SystemProperties.set("sys.boot_completed", "1");
             SystemProperties.set("dev.bootcomplete", "1");
@@ -5242,7 +5220,6 @@
                             }, mConstants.FULL_PSS_MIN_INTERVAL);
                         }
                     });
-            maybeLogUserspaceRebootEvent();
             mUserController.scheduleStartProfiles();
         }
         // UART is on if init's console service is running, send a warning notification.
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..c138a59 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -49,18 +49,7 @@
       ]
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.am."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_am_Presubmit"
     },
     {
       "name": "FrameworksMockingServicesTests",
@@ -78,18 +67,11 @@
     },
     {
       "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"],
-      "name": "FrameworksServicesTests",
-      "options": [
-        { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }
-      ]
+      "name": "FrameworksServicesTests_battery_stats"
     },
     {
       "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index 65f6af7..e7623e0 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -12,12 +12,7 @@
             "name": "CtsAppOps2TestCases"
         },
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.appop"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_appop"
         },
         {
             "name": "FrameworksMockingServicesTests",
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 2cea32a..ca462ce0 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -26,21 +26,7 @@
             ]
         },
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                  "include-filter": "com.android.server.audio"
-                },
-                {
-                  "include-annotation": "android.platform.test.annotations.Presubmit"
-                },
-                {
-                  "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                  "exclude-annotation": "org.junit.Ignore"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_audio"
         }
     ]
 }
diff --git a/services/core/java/com/android/server/compat/TEST_MAPPING b/services/core/java/com/android/server/compat/TEST_MAPPING
index bc1c728..3997bcf 100644
--- a/services/core/java/com/android/server/compat/TEST_MAPPING
+++ b/services/core/java/com/android/server/compat/TEST_MAPPING
@@ -2,12 +2,7 @@
     "presubmit": [
         // Unit tests
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.compat"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_compat"
         },
         // Tests for the TestRule
         {
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/hdmi/TEST_MAPPING b/services/core/java/com/android/server/hdmi/TEST_MAPPING
index 7245ec4..64c06a6 100644
--- a/services/core/java/com/android/server/hdmi/TEST_MAPPING
+++ b/services/core/java/com/android/server/hdmi/TEST_MAPPING
@@ -1,21 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.hdmi"
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_hdmi_Presubmit"
     }
   ],
   "postsubmit": [
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/integrity/TEST_MAPPING b/services/core/java/com/android/server/integrity/TEST_MAPPING
index be8d2e1..5c05fce 100644
--- a/services/core/java/com/android/server/integrity/TEST_MAPPING
+++ b/services/core/java/com/android/server/integrity/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.integrity."
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_integrity"
     },
     {
       "name": "GtsSecurityHostTestCases",
diff --git a/services/core/java/com/android/server/lights/TEST_MAPPING b/services/core/java/com/android/server/lights/TEST_MAPPING
index 17b98ce8..1d2cd3c 100644
--- a/services/core/java/com/android/server/lights/TEST_MAPPING
+++ b/services/core/java/com/android/server/lights/TEST_MAPPING
@@ -9,11 +9,7 @@
       ]
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {"include-filter": "com.android.server.lights"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
-      ]
+      "name": "FrameworksServicesTests_android_server_lights"
     }
   ]
 }
diff --git a/services/core/java/com/android/server/locales/TEST_MAPPING b/services/core/java/com/android/server/locales/TEST_MAPPING
index fd8cddc..26e4685 100644
--- a/services/core/java/com/android/server/locales/TEST_MAPPING
+++ b/services/core/java/com/android/server/locales/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.locales."
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_locales"
     },
     {
       "name": "CtsLocaleManagerHostTestCases"
diff --git a/services/core/java/com/android/server/location/contexthub/TEST_MAPPING b/services/core/java/com/android/server/location/contexthub/TEST_MAPPING
index 2f6aa53..85ea5a4 100644
--- a/services/core/java/com/android/server/location/contexthub/TEST_MAPPING
+++ b/services/core/java/com/android/server/location/contexthub/TEST_MAPPING
@@ -1,21 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.location.contexthub."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_location_contexthub_Presubmit"
     }
   ],
   "imports": [
diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING
index 256d9ba..ffbdf7f 100644
--- a/services/core/java/com/android/server/locksettings/TEST_MAPPING
+++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING
@@ -14,15 +14,7 @@
     ],
     "presubmit": [
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.locksettings."
-                },
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_locksettings"
         }
     ],
     "postsubmit": [
diff --git a/services/core/java/com/android/server/logcat/TEST_MAPPING b/services/core/java/com/android/server/logcat/TEST_MAPPING
index 9041552..5b07cd9 100644
--- a/services/core/java/com/android/server/logcat/TEST_MAPPING
+++ b/services/core/java/com/android/server/logcat/TEST_MAPPING
@@ -1,11 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {"include-filter": "com.android.server.logcat"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
-      ]
+      "name": "FrameworksServicesTests_android_server_logcat_Presubmit"
     }
   ],
   "postsubmit": [
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 7a311bd..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();
@@ -760,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
@@ -1038,6 +1045,7 @@
 
             mUseMeteredFirewallChains = Flags.useMeteredFirewallChains();
             mUseDifferentDelaysForBackgroundChain = Flags.useDifferentDelaysForBackgroundChain();
+            mNeverApplyRulesToCoreUids = Flags.neverApplyRulesToCoreUids();
 
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
@@ -4088,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);
@@ -4878,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.
@@ -5180,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);
     }
 
@@ -6194,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) {
@@ -6241,6 +6254,9 @@
      */
     @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);
@@ -6249,8 +6265,6 @@
             if (chain == FIREWALL_CHAIN_STANDBY) {
                 mUidFirewallStandbyRules.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);
@@ -6295,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/om/TEST_MAPPING b/services/core/java/com/android/server/om/TEST_MAPPING
index 82e7817..ce047bb 100644
--- a/services/core/java/com/android/server/om/TEST_MAPPING
+++ b/services/core/java/com/android/server/om/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.om."
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_om"
     },
     {
       "name": "OverlayDeviceTests"
diff --git a/services/core/java/com/android/server/pdb/TEST_MAPPING b/services/core/java/com/android/server/pdb/TEST_MAPPING
index 9e98023..ed6dfd8 100644
--- a/services/core/java/com/android/server/pdb/TEST_MAPPING
+++ b/services/core/java/com/android/server/pdb/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
     "presubmit": [
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.pdb.PersistentDataBlockServiceTest"
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_pdb"
         }
     ]
 }
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/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
index 1c86c4f..64bcc22 100644
--- a/services/core/java/com/android/server/pm/dex/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.pm.dex"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_pm_dex"
     },
     {
       "name": "DynamicCodeLoggerIntegrationTests"
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c654111..feaf181 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -96,7 +96,6 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.dreams.DreamManagerInternal;
-import android.sysprop.InitProperties;
 import android.sysprop.PowerProperties;
 import android.util.ArrayMap;
 import android.util.IntArray;
@@ -127,7 +126,6 @@
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
-import com.android.server.UserspaceRebootLogger;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.display.feature.DeviceConfigParameterProvider;
@@ -1251,8 +1249,7 @@
             mHalInteractiveModeEnabled = true;
 
             mWakefulnessRaw = WAKEFULNESS_AWAKE;
-            sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1")
-                    || InitProperties.userspace_reboot_in_progress().orElse(false);
+            sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
 
             mNativeWrapper.nativeInit(this);
             mNativeWrapper.nativeSetAutoSuspend(false);
@@ -3945,7 +3942,6 @@
                 throw new UnsupportedOperationException(
                         "Attempted userspace reboot on a device that doesn't support it");
             }
-            UserspaceRebootLogger.noteUserspaceRebootWasRequested();
         }
         if (mHandler == null || !mSystemReady) {
             if (RescueParty.isRecoveryTriggeredReboot()) {
diff --git a/services/core/java/com/android/server/powerstats/TEST_MAPPING b/services/core/java/com/android/server/powerstats/TEST_MAPPING
index 79224a5..0ba1da9 100644
--- a/services/core/java/com/android/server/powerstats/TEST_MAPPING
+++ b/services/core/java/com/android/server/powerstats/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.powerstats"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_powerstats"
     }
   ]
 }
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 2cc931b..291b8db 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.rollback"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_rollback"
     }
   ],
   "imports": [
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 0ffd002..35003af 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -65,6 +65,7 @@
 import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static com.android.server.stats.pull.netstats.NetworkStatsUtils.fromPublicNetworkStats;
 
 import static libcore.io.IoUtils.closeQuietly;
 
@@ -203,7 +204,6 @@
 import com.android.internal.os.StoragedUidIoStatsReader;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.FrameworkStatsLog;
-import com.android.net.module.util.NetworkStatsUtils;
 import com.android.role.RoleManagerLocal;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalManagerRegistry;
@@ -1522,7 +1522,7 @@
                         currentTimeInMillis);
 
         final NetworkStats nonTaggedStats =
-                NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats);
+                fromPublicNetworkStats(queryNonTaggedStats);
         queryNonTaggedStats.close();
         if (!includeTags) return nonTaggedStats;
 
@@ -1531,7 +1531,7 @@
                         currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                         currentTimeInMillis);
         final NetworkStats taggedStats =
-                NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats);
+                fromPublicNetworkStats(queryTaggedStats);
         queryTaggedStats.close();
         return nonTaggedStats.add(taggedStats);
     }
diff --git a/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsUtils.java b/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsUtils.java
new file mode 100644
index 0000000..de58852
--- /dev/null
+++ b/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsUtils.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.stats.pull.netstats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
+import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.ROAMING_ALL;
+import static android.net.NetworkStats.SET_ALL;
+
+import android.app.usage.NetworkStats;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Utility methods for accessing {@link android.net.NetworkStats}.
+ */
+public class NetworkStatsUtils {
+
+    /**
+     * Convert structure from android.app.usage.NetworkStats to android.net.NetworkStats.
+     */
+    public static android.net.NetworkStats fromPublicNetworkStats(
+            NetworkStats publiceNetworkStats) {
+        android.net.NetworkStats stats = new android.net.NetworkStats(0L, 0);
+        while (publiceNetworkStats.hasNextBucket()) {
+            NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+            publiceNetworkStats.getNextBucket(bucket);
+            final android.net.NetworkStats.Entry entry = fromBucket(bucket);
+            stats = stats.addEntry(entry);
+        }
+        return stats;
+    }
+
+    /**
+     * Convert structure from android.app.usage.NetworkStats.Bucket
+     * to android.net.NetworkStats.Entry.
+     */
+    @VisibleForTesting
+    public static android.net.NetworkStats.Entry fromBucket(NetworkStats.Bucket bucket) {
+        return new android.net.NetworkStats.Entry(
+                null /* IFACE_ALL */, bucket.getUid(), convertBucketState(bucket.getState()),
+                convertBucketTag(bucket.getTag()), convertBucketMetered(bucket.getMetered()),
+                convertBucketRoaming(bucket.getRoaming()),
+                convertBucketDefaultNetworkStatus(bucket.getDefaultNetworkStatus()),
+                bucket.getRxBytes(), bucket.getRxPackets(),
+                bucket.getTxBytes(), bucket.getTxPackets(), 0 /* operations */);
+    }
+
+    private static int convertBucketState(int networkStatsSet) {
+        switch (networkStatsSet) {
+            case NetworkStats.Bucket.STATE_ALL: return SET_ALL;
+            case NetworkStats.Bucket.STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT;
+            case NetworkStats.Bucket.STATE_FOREGROUND:
+                return android.net.NetworkStats.SET_FOREGROUND;
+        }
+        return 0;
+    }
+
+    private static int convertBucketTag(int tag) {
+        switch (tag) {
+            case NetworkStats.Bucket.TAG_NONE: return android.net.NetworkStats.TAG_NONE;
+        }
+        return tag;
+    }
+
+    private static int convertBucketMetered(int metered) {
+        switch (metered) {
+            case NetworkStats.Bucket.METERED_ALL: return METERED_ALL;
+            case NetworkStats.Bucket.METERED_NO: return android.net.NetworkStats.METERED_NO;
+            case NetworkStats.Bucket.METERED_YES: return android.net.NetworkStats.METERED_YES;
+        }
+        return 0;
+    }
+
+    private static int convertBucketRoaming(int roaming) {
+        switch (roaming) {
+            case NetworkStats.Bucket.ROAMING_ALL: return ROAMING_ALL;
+            case NetworkStats.Bucket.ROAMING_NO: return android.net.NetworkStats.ROAMING_NO;
+            case NetworkStats.Bucket.ROAMING_YES: return android.net.NetworkStats.ROAMING_YES;
+        }
+        return 0;
+    }
+
+    private static int convertBucketDefaultNetworkStatus(int defaultNetworkStatus) {
+        switch (defaultNetworkStatus) {
+            case NetworkStats.Bucket.DEFAULT_NETWORK_ALL:
+                return DEFAULT_NETWORK_ALL;
+            case NetworkStats.Bucket.DEFAULT_NETWORK_NO:
+                return android.net.NetworkStats.DEFAULT_NETWORK_NO;
+            case NetworkStats.Bucket.DEFAULT_NETWORK_YES:
+                return android.net.NetworkStats.DEFAULT_NETWORK_YES;
+        }
+        return 0;
+    }
+}
diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
index 68eb8eb..480db25 100644
--- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java
+++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
@@ -76,8 +76,6 @@
     // Keep this in sync with the definitions in TraceService
     private static final String INTENT_ACTION_NOTIFY_SESSION_STOPPED =
             "com.android.traceur.NOTIFY_SESSION_STOPPED";
-    private static final String INTENT_ACTION_NOTIFY_SESSION_STOLEN =
-            "com.android.traceur.NOTIFY_SESSION_STOLEN";
 
     private static final int REPORT_BEGIN =
             TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN;
@@ -97,13 +95,12 @@
 
     private final ITracingServiceProxy.Stub mTracingServiceProxy = new ITracingServiceProxy.Stub() {
         /**
-         * Notifies system tracing app that a tracing session has ended. If a session is repurposed
-         * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
-         * there is no buffer available to dump.
+         * Notifies system tracing app that a tracing session has ended. sessionStolen is ignored,
+         * as trace sessions are no longer stolen and are always cloned instead.
          */
         @Override
-        public void notifyTraceSessionEnded(boolean sessionStolen) {
-            TracingServiceProxy.this.notifyTraceur(sessionStolen);
+        public void notifyTraceSessionEnded(boolean sessionStolen /* unused */) {
+            TracingServiceProxy.this.notifyTraceur();
         }
 
         @Override
@@ -132,7 +129,7 @@
         }
     }
 
-    private void notifyTraceur(boolean sessionStolen) {
+    private void notifyTraceur() {
         final Intent intent = new Intent();
 
         try {
@@ -141,11 +138,7 @@
                     PackageManager.MATCH_SYSTEM_ONLY);
 
             intent.setClassName(info.packageName, TRACING_APP_ACTIVITY);
-            if (sessionStolen) {
-                intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOLEN);
-            } else {
-                intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOPPED);
-            }
+            intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOPPED);
 
             final long identity = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/uri/TEST_MAPPING b/services/core/java/com/android/server/uri/TEST_MAPPING
index b42d154..0d756bb 100644
--- a/services/core/java/com/android/server/uri/TEST_MAPPING
+++ b/services/core/java/com/android/server/uri/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
     "presubmit": [
         {
-            "name": "FrameworksServicesTests",
-            "options": [
-                {
-                    "include-filter": "com.android.server.uri."
-                }
-            ]
+            "name": "FrameworksServicesTests_android_server_uri"
         },
         {
             "name": "CtsStorageHostTestCases",
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 07a03eb..762fa07 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -996,6 +996,7 @@
                 // complete configuration.
                 continue;
             }
+            win.updateSurfacePositionIfNeeded();
             win.reportResized();
             mWmService.mResizingWindows.remove(i);
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a310992..4a2694b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4772,6 +4772,9 @@
                     mTransitionController.collect(topActivity);
 
                     final Task lastParentBeforePip = topActivity.getLastParentBeforePip();
+                    // Reset the activity windowing mode to match the parent.
+                    topActivity.getRequestedOverrideConfiguration()
+                            .windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
                     topActivity.reparent(lastParentBeforePip,
                             lastParentBeforePip.getChildCount() /* top */,
                             "movePinnedActivityToOriginalTask");
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..b7446d9 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,
@@ -5194,6 +5190,14 @@
         super.prepareSurfaces();
     }
 
+    void updateSurfacePositionIfNeeded() {
+        if (mWindowFrames.mRelFrame.top == mWindowFrames.mLastRelFrame.top
+                && mWindowFrames.mRelFrame.left == mWindowFrames.mLastRelFrame.left) {
+            return;
+        }
+        updateSurfacePosition(getSyncTransaction());
+    }
+
     @Override
     @VisibleForTesting
     void updateSurfacePosition(Transaction t) {
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
index 6393e11..1db9e8d 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
@@ -1,7 +1,7 @@
 aconfig_declarations {
     name: "device_state_flags",
     package: "com.android.server.policy.feature.flags",
-    container: "system",
+    container: "system_ext",
     srcs: [
         "device_state_flags.aconfig",
     ],
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
index 21e33dd..f827b55 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
@@ -1,5 +1,5 @@
 package: "com.android.server.policy.feature.flags"
-container: "system"
+container: "system_ext"
 
 flag {
     name: "enable_dual_display_blocking"
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index dab3978..8332b8b 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -46,12 +46,12 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.art.ArtManagerLocal;
+import com.android.server.profcollect.Utils;
 import com.android.server.wm.ActivityMetricsLaunchObserver;
 import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.util.Arrays;
-import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -280,11 +280,7 @@
             return;
         }
 
-        // Sample for a fraction of app launches.
-        int traceFrequency = DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                "applaunch_trace_freq", 2);
-        int randomNum = ThreadLocalRandom.current().nextInt(100);
-        if (randomNum < traceFrequency) {
+        if (Utils.withFrequency("applaunch_trace_freq", 2)) {
             BackgroundThread.get().getThreadHandler().post(() -> {
                 try {
                     mIProfcollect.trace_system("applaunch");
@@ -318,12 +314,7 @@
         if (mIProfcollect == null) {
             return;
         }
-        // Sample for a fraction of dex2oat runs.
-        final int traceFrequency =
-            DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                "dex2oat_trace_freq", 25);
-        int randomNum = ThreadLocalRandom.current().nextInt(100);
-        if (randomNum < traceFrequency) {
+        if (Utils.withFrequency("dex2oat_trace_freq", 25)) {
             // Dex2oat could take a while before it starts. Add a short delay before start tracing.
             BackgroundThread.get().getThreadHandler().postDelayed(() -> {
                 try {
@@ -393,27 +384,22 @@
                 if (Arrays.asList(cameraSkipPackages).contains(packageId)) {
                     return;
                 }
-                // Sample for a fraction of camera events.
-                final int traceFrequency =
-                        DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                        "camera_trace_freq", 10);
-                int randomNum = ThreadLocalRandom.current().nextInt(100);
-                if (randomNum >= traceFrequency) {
-                    return;
-                }
-                final int traceDuration = 5000;
-                final String traceTag = "camera";
-                BackgroundThread.get().getThreadHandler().post(() -> {
-                    if (mIProfcollect == null) {
-                        return;
-                    }
-                    try {
-                        mIProfcollect.trace_process(traceTag, "android.hardware.camera.provider",
+                if (Utils.withFrequency("camera_trace_freq", 10)) {
+                    final int traceDuration = 5000;
+                    final String traceTag = "camera";
+                    BackgroundThread.get().getThreadHandler().post(() -> {
+                        if (mIProfcollect == null) {
+                            return;
+                        }
+                        try {
+                            mIProfcollect.trace_process(traceTag,
+                                "android.hardware.camera.provider",
                                 traceDuration);
-                    } catch (RemoteException e) {
-                        Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
-                    }
-                });
+                        } catch (RemoteException e) {
+                            Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
+                        }
+                    });
+                }
             }
         }, null);
     }
diff --git a/services/profcollect/src/com/android/server/profcollect/Utils.java b/services/profcollect/src/com/android/server/profcollect/Utils.java
new file mode 100644
index 0000000..d5ef14c
--- /dev/null
+++ b/services/profcollect/src/com/android/server/profcollect/Utils.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.profcollect;
+
+import android.provider.DeviceConfig;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public final class Utils {
+
+  public static boolean withFrequency(String configName, int defaultFrequency) {
+        int threshold = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, configName, defaultFrequency);
+        int randomNum = ThreadLocalRandom.current().nextInt(100);
+        return randomNum < threshold;
+    }
+
+}
\ No newline at end of file
diff --git a/services/proguard.flags b/services/proguard.flags
index f84eff7..1e7e9b0 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -57,9 +57,6 @@
 -keep public class com.android.server.utils.Slogf { *; }
 
 # Referenced in wear-service
-# HIDL interfaces
--keep public class android.hidl.base.** { *; }
--keep public class android.hidl.manager.** { *; }
 -keep public class com.android.server.wm.WindowManagerInternal { *; }
 
 # JNI keep rules
@@ -112,8 +109,23 @@
 -keep,allowoptimization,allowaccessmodification class com.android.server.SystemService { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.SystemService$TargetUser { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.usage.StorageStatsManagerLocal { *; }
--keep,allowoptimization,allowaccessmodification class com.android.internal.util.** { *; }
--keep,allowoptimization,allowaccessmodification class android.os.** { *; }
+
+# Prevent optimizations of any statically linked code that may shadow code in
+# the bootclasspath. See also StrictJavaPackagesTest for details on exceptions.
+# TODO(b/222468116): Resolve such collisions in the build system.
+-keep public class android.gsi.** { *; }
+-keep public class android.hidl.base.** { *; }
+-keep public class android.hidl.manager.** { *; }
+-keep public class android.os.** { *; }
+-keep public class com.android.internal.util.** { *; }
+-keep public class com.android.modules.utils.build.** { *; }
+# Also suppress related duplicate type warnings for the above kept classes.
+-dontwarn android.gsi.**
+-dontwarn android.hidl.base.**
+-dontwarn android.hidl.manager.**
+-dontwarn android.os.**
+-dontwarn com.android.internal.util.**
+-dontwarn com.android.modules.utils.build.**
 
 # CoverageService guards optional jacoco class references with a runtime guard, so we can safely
 # suppress build-time warnings.
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/Android.bp b/services/tests/servicestests/Android.bp
index 7b7ed1d..0f10b8c 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -83,6 +83,7 @@
         "securebox",
         "flag-junit",
         "ravenwood-junit",
+        "net-tests-utils",
         "net_flags_lib",
         "CtsVirtualDeviceCommonLib",
         "com_android_server_accessibility_flags_lib",
@@ -270,6 +271,10 @@
         "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
 }
 
+FLAKY = [
+    "androidx.test.filters.FlakyTest",
+]
+
 FLAKY_AND_IGNORED = [
     "androidx.test.filters.FlakyTest",
     "org.junit.Ignore",
@@ -326,7 +331,7 @@
     base: "FrameworksServicesTests",
     test_suites: ["device-tests"],
     include_filters: ["com.android.server.recoverysystem."],
-    exclude_annotations: ["androidx.test.filters.FlakyTest"],
+    exclude_annotations: FLAKY,
 }
 
 // server pm TEST_MAPPING
@@ -355,3 +360,319 @@
     test_suites: ["device-tests"],
     include_filters: ["com.android.server.os."],
 }
+
+test_module_config {
+    name: "FrameworksServicesTests_presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_job_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.job"],
+    exclude_annotations: [
+        "androidx.test.filters.LargeTest",
+        "androidx.test.filters.FlakyTest",
+    ],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_job",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_tare_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.tare"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_tare",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_usage_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.usage"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_usage",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.usage"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_battery_stats",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.am.BatteryStatsServiceTest"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_accessibility_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.accessibility"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_accessibility",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.accessibility"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_binary_transparency",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.BinaryTransparencyServiceTest"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_pinner_service",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.PinnerServiceTest"],
+    exclude_annotations: ["org.junit.Ignore"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_am_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.am."],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_am",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.am."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_appop",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.appop"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_audio",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.audio"],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_compat",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.compat"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_hdmi_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.hdmi"],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_hdmi",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.hdmi"],
+    exclude_annotations: ["org.junit.Ignore"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_integrity",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.integrity."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_lights",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.lights"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_locales",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.locales."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_location_contexthub_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.location.contexthub."],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_locksettings",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.locksettings."],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_logcat_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.logcat"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_logcat",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.logcat"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_net_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.net."],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_om",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.om."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_pdb",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.pdb.PersistentDataBlockServiceTest"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_pm_dex",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.pm.dex"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_policy_Presubmit",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.policy."],
+    include_annotations: ["android.platform.test.annotations.Presubmit"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_policy",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_power",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_power_hint",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.power.hint"],
+    exclude_annotations: FLAKY,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_powerstats",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.powerstats"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_rollback",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.rollback"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_uri",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.uri."],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_com_android_server_location_contexthub",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.location.contexthub."],
+    include_annotations: ["android.platform.test.annotations.Postsubmit"],
+    exclude_annotations: FLAKY_AND_IGNORED,
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_usage",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.usage"],
+    exclude_filters: ["com.android.server.usage.StorageStatsServiceTest"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_soundtrigger_middleware",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.soundtrigger_middleware"],
+}
+
+test_module_config {
+    name: "FrameworksServicesTests_android_server_input",
+    base: "FrameworksServicesTests",
+    test_suites: ["device-tests"],
+    include_filters: ["com.android.server.input"],
+}
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
index 24561c5..3d09da3 100644
--- a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS
@@ -1,3 +1,4 @@
-# Bug component: 544200
+# Bug component: 1040349
 
-include /core/java/android/view/contentcapture/OWNERS
+include /core/java/android/view/contentprotection/OWNERS
+
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/tests/servicestests/src/com/android/server/stats/pull/netstats/NetworkStatsUtilsTest.kt b/services/tests/servicestests/src/com/android/server/stats/pull/netstats/NetworkStatsUtilsTest.kt
new file mode 100644
index 0000000..c560c04
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/stats/pull/netstats/NetworkStatsUtilsTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.stats.pull.netstats
+
+import android.net.NetworkStats
+import android.net.NetworkStats.DEFAULT_NETWORK_NO
+import android.net.NetworkStats.DEFAULT_NETWORK_YES
+import android.net.NetworkStats.Entry
+import android.net.NetworkStats.METERED_NO
+import android.net.NetworkStats.ROAMING_NO
+import android.net.NetworkStats.ROAMING_YES
+import android.net.NetworkStats.SET_DEFAULT
+import android.net.NetworkStats.TAG_NONE
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.testutils.assertEntryEquals
+import com.android.testutils.assertNetworkStatsEquals
+import com.android.testutils.makePublicStatsFromAndroidNetStats
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when`
+
+/**
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:NetworkStatsUtilsTest
+ */
+@RunWith(AndroidJUnit4::class)
+class NetworkStatsUtilsTest {
+
+    @Test
+    fun testBucketToEntry() {
+        val bucket = makeMockBucket(android.app.usage.NetworkStats.Bucket.UID_ALL,
+                android.app.usage.NetworkStats.Bucket.TAG_NONE,
+                android.app.usage.NetworkStats.Bucket.STATE_DEFAULT,
+                android.app.usage.NetworkStats.Bucket.METERED_YES,
+                android.app.usage.NetworkStats.Bucket.ROAMING_NO,
+                android.app.usage.NetworkStats.Bucket.DEFAULT_NETWORK_ALL, 1024, 8, 2048, 12)
+        val entry = NetworkStatsUtils.fromBucket(bucket)
+        val expectedEntry = NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL,
+                NetworkStats.SET_DEFAULT, NetworkStats.TAG_NONE, NetworkStats.METERED_YES,
+                NetworkStats.ROAMING_NO, NetworkStats.DEFAULT_NETWORK_ALL, 1024, 8, 2048, 12,
+                0 /* operations */)
+
+        assertEntryEquals(expectedEntry, entry)
+    }
+
+    @Test
+    fun testPublicStatsToAndroidNetStats() {
+        val uid1 = 10001
+        val uid2 = 10002
+        val testIface = "wlan0"
+        val testAndroidNetStats = NetworkStats(0L, 3)
+                .addEntry(Entry(testIface, uid1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3))
+                .addEntry(Entry(
+                        testIface, uid2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 2, 7, 2, 5, 7))
+                .addEntry(Entry(testIface, uid2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 4, 5, 3, 1, 8))
+        val publicStats: android.app.usage.NetworkStats =
+                makePublicStatsFromAndroidNetStats(testAndroidNetStats)
+        val androidNetStats: NetworkStats =
+                NetworkStatsUtils.fromPublicNetworkStats(publicStats)
+
+        // 1. The public `NetworkStats` class does not include interface information.
+        //    Interface details must be removed and items with duplicated
+        //    keys need to be merged before making any comparisons.
+        // 2. The public `NetworkStats` class lacks an operations field.
+        //    Thus, the information will not be preserved during the conversion.
+        val expectedStats = NetworkStats(0L, 2)
+                .addEntry(Entry(null, uid1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 0))
+                .addEntry(Entry(null, uid2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 6, 12, 5, 6, 0))
+        assertNetworkStatsEquals(expectedStats, androidNetStats)
+    }
+
+    private fun makeMockBucket(
+            uid: Int,
+            tag: Int,
+            state: Int,
+            metered: Int,
+            roaming: Int,
+            defaultNetwork: Int,
+            rxBytes: Long,
+            rxPackets: Long,
+            txBytes: Long,
+            txPackets: Long
+    ): android.app.usage.NetworkStats.Bucket {
+        val ret: android.app.usage.NetworkStats.Bucket =
+                mock(android.app.usage.NetworkStats.Bucket::class.java)
+        doReturn(uid).`when`(ret).getUid()
+        doReturn(tag).`when`(ret).getTag()
+        doReturn(state).`when`(ret).getState()
+        doReturn(metered).`when`(ret).getMetered()
+        doReturn(roaming).`when`(ret).getRoaming()
+        doReturn(defaultNetwork).`when`(ret).getDefaultNetworkStatus()
+        doReturn(rxBytes).`when`(ret).getRxBytes()
+        doReturn(rxPackets).`when`(ret).getRxPackets()
+        doReturn(txBytes).`when`(ret).getTxBytes()
+        doReturn(txPackets).`when`(ret).getTxPackets()
+        return ret
+    }
+}
\ No newline at end of file
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 6e84543..c878054 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -1,23 +1,10 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.app.usage"
-        }
-      ]
+      "name": "FrameworksCoreTests_usage"
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.usage"
-        },
-        {
-          "exclude-filter": "com.android.server.usage.StorageStatsServiceTest"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_usage"
     },
     {
       "name": "CtsBRSTestCases",
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/TEST_MAPPING b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/TEST_MAPPING
index 9ed894b..509d95e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/TEST_MAPPING
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/TEST_MAPPING
@@ -1,12 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.soundtrigger_middleware"
-        }
-      ]
+      "name": "FrameworksServicesTests_android_server_soundtrigger_middleware"
     }
   ]
 }
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 660cd47..59db66b 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -24,9 +24,10 @@
 import com.github.javaparser.ParserConfiguration
 import com.github.javaparser.StaticJavaParser
 import com.github.javaparser.ast.CompilationUnit
+import com.github.javaparser.ast.Modifier
 import com.github.javaparser.ast.NodeList
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
-import com.github.javaparser.ast.body.InitializerDeclaration
+import com.github.javaparser.ast.expr.AssignExpr
 import com.github.javaparser.ast.expr.FieldAccessExpr
 import com.github.javaparser.ast.expr.MethodCallExpr
 import com.github.javaparser.ast.expr.NameExpr
@@ -34,7 +35,10 @@
 import com.github.javaparser.ast.expr.ObjectCreationExpr
 import com.github.javaparser.ast.expr.SimpleName
 import com.github.javaparser.ast.expr.StringLiteralExpr
+import com.github.javaparser.ast.expr.VariableDeclarationExpr
 import com.github.javaparser.ast.stmt.BlockStmt
+import com.github.javaparser.ast.stmt.ReturnStmt
+import com.github.javaparser.ast.type.ClassOrInterfaceType
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileNotFoundException
@@ -180,6 +184,7 @@
         groups: Map<String, LogGroup>,
         protoLogGroupsClassName: String
     ) {
+        var needsCreateLogGroupsMap = false
         classDeclaration.fields.forEach { field ->
             field.getAnnotationByClass(ProtoLogToolInjected::class.java)
                     .ifPresent { annotationExpr ->
@@ -207,39 +212,55 @@
                                             } ?: NullLiteralExpr())
                                 }
                                 ProtoLogToolInjected.Value.LOG_GROUPS.name -> {
-                                    val initializerBlockStmt = BlockStmt()
-                                    for (group in groups) {
-                                        initializerBlockStmt.addStatement(
-                                            MethodCallExpr()
-                                                    .setName("put")
-                                                    .setArguments(
-                                                        NodeList(StringLiteralExpr(group.key),
-                                                            FieldAccessExpr()
-                                                                    .setScope(
-                                                                        NameExpr(
-                                                                            protoLogGroupsClassName
-                                                                        ))
-                                                                    .setName(group.value.name)))
-                                        )
-                                        group.key
-                                    }
-
-                                    val treeMapCreation = ObjectCreationExpr()
-                                            .setType("TreeMap<String, IProtoLogGroup>")
-                                            .setAnonymousClassBody(NodeList(
-                                                InitializerDeclaration().setBody(
-                                                    initializerBlockStmt
-                                                )
-                                            ))
-
+                                    needsCreateLogGroupsMap = true
                                     field.setFinal(true)
-                                    field.variables.first().setInitializer(treeMapCreation)
+                                    field.variables.first().setInitializer(
+                                        MethodCallExpr().setName("createLogGroupsMap"))
                                 }
                                 else -> error("Unhandled ProtoLogToolInjected value: $valueName.")
                             }
                         }
                     }
         }
+
+        if (needsCreateLogGroupsMap) {
+            val body = BlockStmt()
+            body.addStatement(AssignExpr(
+                VariableDeclarationExpr(
+                    ClassOrInterfaceType("TreeMap<String, IProtoLogGroup>"),
+                    "result"
+                ),
+                ObjectCreationExpr().setType("TreeMap<String, IProtoLogGroup>"),
+                AssignExpr.Operator.ASSIGN
+            ))
+            for (group in groups) {
+                body.addStatement(
+                    MethodCallExpr(
+                        NameExpr("result"),
+                        "put",
+                        NodeList(
+                                StringLiteralExpr(group.key),
+                                FieldAccessExpr()
+                                        .setScope(
+                                            NameExpr(
+                                                protoLogGroupsClassName
+                                            ))
+                                        .setName(group.value.name)
+                        )
+                    )
+                )
+            }
+            body.addStatement(ReturnStmt(NameExpr("result")))
+
+            val method = classDeclaration.addMethod(
+                "createLogGroupsMap",
+                Modifier.Keyword.PRIVATE,
+                Modifier.Keyword.STATIC,
+                Modifier.Keyword.FINAL
+            )
+            method.setType("TreeMap<String, IProtoLogGroup>")
+            method.setBody(body)
+        }
     }
 
     private fun tryParse(code: String, fileName: String): CompilationUnit {
diff --git a/tools/systemfeatures/Android.bp b/tools/systemfeatures/Android.bp
new file mode 100644
index 0000000..aca25eb
--- /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 --feature-apis=WATCH > $(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: --feature-apis=WATCH,PC > $(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/src/com/android/systemfeatures/SystemFeaturesGenerator.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
new file mode 100644
index 0000000..e537ffc
--- /dev/null
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
@@ -0,0 +1,267 @@
+/*
+ * 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
+ *           --feature-apis=WATCH,PC,LEANBACK
+ * </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 hasFeaturePc(Context context);
+ *     public static boolean hasFeatureLeanback(Context context);
+ *     public static Boolean maybeHasFeature(String feature, int version);
+ * }
+ * </pre>
+ */
+object SystemFeaturesGenerator {
+    private const val FEATURE_ARG = "--feature="
+    private const val FEATURE_APIS_ARG = "--feature-apis="
+    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)")
+        println("                           This will always generate associated query APIs,")
+        println("                           adding to or replacing those from `--feature-apis=`.")
+        println("  --feature-apis=\$NAME_1,\$NAME_2")
+        println("                           A comma-separated set of features for which to always")
+        println("                           generate named query APIs. If a feature in this set is")
+        println("                           not explicitly defined via `--feature=`, then a simple")
+        println("                           runtime passthrough API will be generated, regardless")
+        println("                           of the `--readonly` flag. This allows decoupling the")
+        println("                           API surface from variations in device feature sets.")
+    }
+
+    /** 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 featureArgs = mutableListOf<FeatureArg>()
+        // We could just as easily hardcode this list, as the static API surface should change
+        // somewhat infrequently, but this decouples the codegen from the framework completely.
+        val featureApiArgs = mutableSetOf<String>()
+        for (arg in args) {
+            when {
+                arg.startsWith(READONLY_ARG) ->
+                    readonly = arg.substring(READONLY_ARG.length).toBoolean()
+                arg.startsWith(FEATURE_ARG) -> {
+                    featureArgs.add(parseFeatureArg(arg))
+                }
+                arg.startsWith(FEATURE_APIS_ARG) -> {
+                    featureApiArgs.addAll(
+                        arg.substring(FEATURE_APIS_ARG.length).split(",").map {
+                            parseFeatureName(it)
+                        }
+                    )
+                }
+                else -> outputClassName = ClassName.bestGuess(arg)
+            }
+        }
+
+        // First load in all of the feature APIs we want to generate. Explicit feature definitions
+        // will then override this set with the appropriate readonly and version value.
+        val features = mutableMapOf<String, FeatureInfo>()
+        featureApiArgs.associateByTo(
+            features,
+            { it },
+            { FeatureInfo(it, version = null, readonly = false) },
+        )
+        featureArgs.associateByTo(
+            features,
+            { it.name },
+            { FeatureInfo(it.name, it.version, readonly) },
+        )
+
+        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, features.values)
+        addMaybeFeatureMethodToClass(classBuilder, features.values)
+
+        // 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): FeatureArg {
+        val featureArgs = arg.substring(FEATURE_ARG.length).split(":")
+        val name = parseFeatureName(featureArgs[0])
+        val version = featureArgs.getOrNull(1)?.toIntOrNull()
+        return FeatureArg(name, version)
+    }
+
+    private fun parseFeatureName(name: String): String =
+        if (name.startsWith("FEATURE_")) name else "FEATURE_$name"
+
+    /*
+     * 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,
+        features: Collection<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 (feature.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())
+        }
+
+        // This is a trivial method, even if unused based on readonly-codegen, it does little harm
+        // to always include it.
+        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,
+        features: Collection<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")
+
+        var hasSwitchBlock = false
+        for (feature in features) {
+            // We only return non-null results for queries against readonly-defined features.
+            if (!feature.readonly) {
+                continue
+            }
+            if (!hasSwitchBlock) {
+                // As an optimization, only create the switch block if needed. Even an empty
+                // switch-on-string block can induce a hash, which we can avoid if readonly
+                // support is completely disabled.
+                hasSwitchBlock = true
+                methodBuilder.beginControlFlow("switch (featureName)")
+            }
+            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")
+            }
+        }
+        if (hasSwitchBlock) {
+            methodBuilder.addCode("default: ")
+            methodBuilder.addStatement("break")
+            methodBuilder.endControlFlow()
+        }
+        methodBuilder.addStatement("return null")
+        builder.addMethod(methodBuilder.build())
+    }
+
+    private data class FeatureArg(val name: String, val version: Int?)
+
+    private data class FeatureInfo(val name: String, val version: Int?, val readonly: Boolean)
+}
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..db67048
--- /dev/null
+++ b/tools/systemfeatures/tests/PackageManager.java
@@ -0,0 +1,31 @@
+/*
+ * 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_PC = "pc";
+    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..6dfd244
--- /dev/null
+++ b/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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();
+
+        // Also ensure we fall back to the PackageManager for feature APIs without an accompanying
+        // versioned feature definition.
+        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();
+    }
+
+    @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 feature APIs without an associated feature definition, conditional queries should
+        // report null, and explicit queries should report runtime-defined versions.
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(true);
+        assertThat(RoFeatures.hasFeaturePc(mContext)).isTrue();
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(false);
+        assertThat(RoFeatures.hasFeaturePc(mContext)).isFalse();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, -1)).isNull();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, 0)).isNull();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, 100)).isNull();
+
+        // 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();
+    }
+}