Merge "Add a way to configure log levels" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 9fc4fff..960bb5c 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -279,6 +279,7 @@
     name: "android_nfc_flags_aconfig_c_lib",
     vendor_available: true,
     aconfig_declarations: "android.nfc.flags-aconfig",
+    min_sdk_version: "34",
     apex_available: [
         "//apex_available:platform",
         "com.android.nfcservices",
@@ -575,6 +576,8 @@
     min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
+        "com.android.art.debug",
         "com.android.permission",
     ],
 }
diff --git a/Android.bp b/Android.bp
index 66a0077..20e58ed 100644
--- a/Android.bp
+++ b/Android.bp
@@ -368,6 +368,7 @@
         "view-inspector-annotation-processor",
         "staledataclass-annotation-processor",
         "error_prone_android_framework",
+        "systemfeatures-metadata-processor",
     ],
     // Exports needed for staledataclass-annotation-processor, see b/139342589.
     javacflags: [
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5e69ec1..fb7030f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6859,21 +6859,44 @@
 
     final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
         if (start) {
-            try {
-                switch (profileType) {
-                    default:
+            switch (profileType) {
+                case ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD:
+                    if (!com.android.art.flags.Flags.alwaysEnableProfileCode()) {
+                        Slog.w(TAG, "Low overhead tracing feature is not enabled");
+                        break;
+                    }
+                    VMDebug.startLowOverheadTrace();
+                    break;
+                default:
+                    try {
                         mProfiler.setProfiler(profilerInfo);
                         mProfiler.startProfiling();
                         break;
-                }
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
-                        + " -- can the process access this path?");
-            } finally {
-                profilerInfo.closeFd();
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
+                                + " -- can the process access this path?");
+                    } finally {
+                        profilerInfo.closeFd();
+                    }
             }
         } else {
             switch (profileType) {
+                case ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD:
+                    if (!com.android.art.flags.Flags.alwaysEnableProfileCode()) {
+                        if (profilerInfo != null) {
+                            profilerInfo.closeFd();
+                        }
+                        Slog.w(TAG, "Low overhead tracing feature is not enabled");
+                        break;
+                    }
+                    if (profilerInfo != null) {
+                        FileDescriptor fd = profilerInfo.profileFd.getFileDescriptor();
+                        VMDebug.TraceDestination dst =
+                                VMDebug.TraceDestination.fromFileDescriptor(fd);
+                        VMDebug.dumpLowOverheadTrace(dst);
+                    }
+                    VMDebug.stopLowOverheadTrace();
+                    break;
                 default:
                     mProfiler.stopProfiling();
                     break;
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java
index bcae22a..0348b6d 100644
--- a/core/java/android/app/ProfilerInfo.java
+++ b/core/java/android/app/ProfilerInfo.java
@@ -32,6 +32,12 @@
  * {@hide}
  */
 public class ProfilerInfo implements Parcelable {
+    // Regular profiling which provides different modes of profiling at some performance cost.
+    public static final int PROFILE_TYPE_REGULAR = 0;
+
+    // Low overhead profiling that captures a simple sliding window of past events.
+    public static final int PROFILE_TYPE_LOW_OVERHEAD = 1;
+
     // Version of the profiler output
     public static final int OUTPUT_VERSION_DEFAULT = 1;
     // CLOCK_TYPE_DEFAULT chooses the default used by ART. ART uses CLOCK_TYPE_DUAL by default (see
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3971e98..759d191 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3116,6 +3116,16 @@
     public static final long MAXIMUM_VERIFICATION_TIMEOUT = 60*60*1000;
 
     /**
+     * As the generated feature count is useful for classes that may not be compiled in the same
+     * annotation processing unit as PackageManager, we redeclare it here for visibility.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static final int SDK_FEATURE_COUNT =
+            com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT;
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's
      * audio pipeline is low-latency, more suitable for audio applications sensitive to delays or
      * lag in sound input or output.
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index a86396c..0fedf8e 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -65,7 +65,7 @@
     }
 
     /**
-     * Creates a AF_LOCAL/UNIX domain stream socket with given socket type
+     * Creates a AF_LOCAL/UNIX domain socket with the given socket type.
      *
      * @param sockType either {@link #SOCKET_DGRAM}, {@link #SOCKET_STREAM}
      * or {@link #SOCKET_SEQPACKET}
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 5d1d758..392b42d 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -105,6 +105,7 @@
     namespace: "biometrics"
     description: "Clear StrongAuth on add credential"
     bug: "320817991"
+    is_exported: true
 }
 
 flag {
@@ -127,4 +128,5 @@
     namespace: "hardware_backed_security"
     description: "Feature flag for exposing KeyStore grant APIs"
     bug: "351158708"
+    is_exported: true
 }
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index 5f9f6bd..b6f0270 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -1,6 +1,6 @@
 # Bug component: 533220
-
 include /core/java/android/app/assist/OWNERS
+atneya@google.com
 
 # The owner here should not be assist owner
 adudani@google.com
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTest.java b/core/tests/coretests/src/android/content/pm/PackageManagerTest.java
index 20421d1..d080ee7 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTest.java
@@ -24,6 +24,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageManagerTest {
@@ -46,4 +49,25 @@
     public void testResolveInfoFlags() throws Exception {
         assertThat(PackageManager.ResolveInfoFlags.of(42L).getValue()).isEqualTo(42L);
     }
+
+    @Test
+    public void testSdkFeatureCount() throws Exception {
+        // Check to make sure the system feature `SdkConst` annotation processor yields sensible
+        // results. We don't care about the exactness, just that it's not pathologically wrong.
+        assertThat(PackageManager.SDK_FEATURE_COUNT).isGreaterThan(150);
+        assertThat(PackageManager.SDK_FEATURE_COUNT).isLessThan(500);
+        assertThat(PackageManager.SDK_FEATURE_COUNT)
+                .isWithin(50)
+                .of(getApproximateFeatureCountUsingReflection());
+    }
+
+    /* Return a ballpark estimate of the feature count using FEATURE_ field names. */
+    private static int getApproximateFeatureCountUsingReflection() {
+        return (int)
+                Arrays.stream(PackageManager.class.getFields())
+                        .filter(field -> Modifier.isStatic(field.getModifiers()))
+                        .filter(field -> Modifier.isFinal(field.getModifiers()))
+                        .filter(field -> field.getName().startsWith("FEATURE_"))
+                        .count();
+    }
 }
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index b9a12ad..9758cdd7 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -28,11 +28,10 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
 import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
@@ -52,7 +51,7 @@
 import java.util.concurrent.Executors;
 
 @RunWith(AndroidJUnit4.class)
-@IgnoreUnderRavenwood(blockedBy = PowerManager.class)
+@DisabledOnRavenwood(blockedBy = PowerManager.class)
 public class PowerManagerTest {
 
     private static final String TAG = "PowerManagerTest";
@@ -77,19 +76,14 @@
             String[] keys, String[] values);
 
     static {
-        if (!RavenwoodRule.isUnderRavenwood()) {
+        if (!RavenwoodRule.isOnRavenwood()) {
             System.loadLibrary("powermanagertest_jni");
         }
     }
 
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
     // Required for RequiresFlagsEnabled and RequiresFlagsDisabled annotations to take effect.
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
-            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
-            : DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     /**
      * Setup any common data for the upcoming tests.
diff --git a/core/tests/coretests/src/android/os/WorkDurationUnitTest.java b/core/tests/coretests/src/android/os/WorkDurationUnitTest.java
index fcdc590..c6474c9 100644
--- a/core/tests/coretests/src/android/os/WorkDurationUnitTest.java
+++ b/core/tests/coretests/src/android/os/WorkDurationUnitTest.java
@@ -18,12 +18,10 @@
 
 import static org.junit.Assert.assertThrows;
 
-import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
-import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -34,16 +32,11 @@
 import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidJUnit4.class)
-@IgnoreUnderRavenwood(blockedBy = WorkDuration.class)
+@DisabledOnRavenwood(blockedBy = WorkDuration.class)
 public class WorkDurationUnitTest {
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
     // Required for RequiresFlagsEnabled and RequiresFlagsDisabled annotations to take effect.
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
-            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
-            : DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     @Before
     public void setUp() {
diff --git a/omapi/aidl/Android.bp b/omapi/aidl/Android.bp
index e71597a..3916bf3 100644
--- a/omapi/aidl/Android.bp
+++ b/omapi/aidl/Android.bp
@@ -24,6 +24,7 @@
     backend: {
         java: {
             sdk_version: "module_current",
+            min_sdk_version: "35", // Make it 36 once available.
             apex_available: [
                 "//apex_available:platform",
                 "com.android.nfcservices",
diff --git a/packages/Vcn/framework-b/Android.bp b/packages/Vcn/framework-b/Android.bp
index be64bb1..8b010c7 100644
--- a/packages/Vcn/framework-b/Android.bp
+++ b/packages/Vcn/framework-b/Android.bp
@@ -40,5 +40,28 @@
         "android.net.vcn",
     ],
 
+    impl_library_visibility: [
+        // Using for test only
+        "//cts/tests/netlegacy22.api",
+        "//cts/tests/tests/vcn",
+        "//external/sl4a:__subpackages__",
+        "//frameworks/base/core/tests/bandwidthtests",
+        "//frameworks/base/core/tests/benchmarks",
+        "//frameworks/base/core/tests/utillib",
+        "//frameworks/base/services/tests/VpnTests",
+        "//frameworks/base/tests/vcn",
+        "//frameworks/opt/telephony/tests/telephonytests",
+        "//packages/modules/CaptivePortalLogin/tests",
+        "//packages/modules/Connectivity/staticlibs/testutils",
+        "//packages/modules/Connectivity/staticlibs/tests:__subpackages__",
+        "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
+        "//packages/modules/Connectivity/tests:__subpackages__",
+        "//packages/modules/Connectivity/thread/tests:__subpackages__",
+        "//packages/modules/IPsec/tests/iketests",
+        "//packages/modules/NetworkStack",
+        "//packages/modules/NetworkStack/tests:__subpackages__",
+        "//packages/modules/Wifi/service/tests/wifitests",
+    ],
+
     // TODO: b/375213246 Expose this library to Tethering module
 }
diff --git a/ravenwood/test-authors.md b/ravenwood/test-authors.md
index c29fb7f..6d82a74 100644
--- a/ravenwood/test-authors.md
+++ b/ravenwood/test-authors.md
@@ -106,45 +106,6 @@
 
 > **Note:** There's a known bug #308854804 where `TEST_MAPPING` is not being applied, so we're currently planning to run all Ravenwood tests unconditionally in presubmit for changes to `frameworks/base/` and `cts/` until there is a better path forward.
 
-## Strategies for feature flags
-
-Ravenwood supports writing tests against logic that uses feature flags through the existing `SetFlagsRule` infrastructure maintained by the feature flagging team:
-
-```
-import android.platform.test.flag.junit.SetFlagsRule;
-
-@RunWith(AndroidJUnit4.class)
-public class MyCodeTest {
-    @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(SetFlagsRule.DefaultInitValueType.NULL_DEFAULT);
-
-    @Test
-    public void testEnabled() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_MY_FLAG);
-        // verify test logic that depends on flag being enabled
-    }
-```
-
-This naturally composes together well with any `RavenwoodRule` that your test may need.
-
-While `SetFlagsRule` is generally a best-practice (as it can explicitly confirm behaviors for both "on" and "off" states), you may need to write tests that use `CheckFlagsRule` (such as when writing CTS).  Ravenwood currently supports `CheckFlagsRule` by offering "all-on" and "all-off" behaviors:
-
-```
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-@RunWith(AndroidJUnit4.class)
-public class MyCodeTest {
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isUnderRavenwood()
-            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
-            : DeviceFlagsValueProvider.createCheckFlagsRule();
-```
-
-Ravenwood currently doesn't have knowledge of the "default" value of any flags, so using `createAllOnCheckFlagsRule()` is recommended to verify the widest possible set of behaviors.  The example code above falls back to using default values from `DeviceFlagsValueProvider` when not running on Ravenwood.
-
 ## Strategies for migration/bivalent tests
 
 Ravenwood aims to support tests that are written in a “bivalent” way, where the same test code can be dual-compiled to run on both a real Android device and under a Ravenwood environment.
diff --git a/services/core/Android.bp b/services/core/Android.bp
index f08c876..349f3ee 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -233,7 +233,6 @@
         "core_os_flags_lib",
         "connectivity_flags_lib",
         "dreams_flags_lib",
-        "aconfig_flags_java",
         "aconfig_new_storage_flags_lib",
         "powerstats_flags_lib",
         "locksettings_flags_lib",
diff --git a/services/core/java/com/android/server/SecurityStateManagerService.java b/services/core/java/com/android/server/SecurityStateManagerService.java
index 98039be..fe21fbd 100644
--- a/services/core/java/com/android/server/SecurityStateManagerService.java
+++ b/services/core/java/com/android/server/SecurityStateManagerService.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.ISecurityStateManager;
@@ -56,6 +57,15 @@
 
     @Override
     public Bundle getGlobalSecurityState() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return getGlobalSecurityStateInternal();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private Bundle getGlobalSecurityStateInternal() {
         Bundle globalSecurityState = new Bundle();
         globalSecurityState.putString(KEY_SYSTEM_SPL, Build.VERSION.SECURITY_PATCH);
         globalSecurityState.putString(KEY_VENDOR_SPL,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4a4a1b4..0152f94 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7609,7 +7609,7 @@
     }
 
     void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo,
-            ApplicationInfo sdkSandboxClientApp) {
+            ApplicationInfo sdkSandboxClientApp, int profileType) {
         synchronized (mAppProfiler.mProfilerLock) {
             if (!Build.IS_DEBUGGABLE) {
                 boolean isAppDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
@@ -7625,7 +7625,7 @@
                             + "and not profileable by shell: " + app.packageName);
                 }
             }
-            mAppProfiler.setProfileAppLPf(processName, profilerInfo);
+            mAppProfiler.setProfileAppLPf(processName, profilerInfo, profileType);
         }
     }
 
@@ -17883,7 +17883,8 @@
                     + android.Manifest.permission.SET_ACTIVITY_WATCHER);
         }
 
-        if (start && (profilerInfo == null || profilerInfo.profileFd == null)) {
+        if (start && profileType == ProfilerInfo.PROFILE_TYPE_REGULAR
+                && (profilerInfo == null || profilerInfo.profileFd == null)) {
             throw new IllegalArgumentException("null profile info or fd");
         }
 
@@ -19499,7 +19500,9 @@
                     }
 
                     if (profilerInfo != null) {
-                        setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo, null);
+                        // We only support normal method tracing along with app startup for now.
+                        setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo,
+                                null, /*profileType= */ ProfilerInfo.PROFILE_TYPE_REGULAR);
                     }
                     wmLock.notify();
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 955437b..1853973 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1081,7 +1081,7 @@
         String profileFile = null;
         boolean start = false;
         int userId = UserHandle.USER_CURRENT;
-        int profileType = 0;
+        int profileType = ProfilerInfo.PROFILE_TYPE_REGULAR;
         mSamplingInterval = 0;
         mStreaming = false;
         mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT;
@@ -1123,6 +1123,18 @@
                 }
             }
             process = getNextArgRequired();
+        } else if ("lowoverhead".equals(cmd)) {
+            // This is an experimental low overhead profiling.
+            profileType = ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD;
+            cmd = getNextArgRequired();
+            if ("start".equals(cmd)) {
+                start = true;
+            } else if ("stop".equals(cmd)) {
+                start = false;
+            } else {
+                throw new IllegalArgumentException("Profile command not valid");
+            }
+            process = getNextArgRequired();
         } else {
             // Compatibility with old syntax: process is specified first.
             process = cmd;
@@ -1142,7 +1154,12 @@
         ParcelFileDescriptor fd = null;
         ProfilerInfo profilerInfo = null;
 
-        if (start) {
+        // For regular method tracing  profileFile should be provided with the start command. For
+        // low overhead method tracing the profileFile is optional and provided with the stop
+        // command.
+        if ((start && profileType == ProfilerInfo.PROFILE_TYPE_REGULAR)
+                || (profileType == ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD
+                  && !start && getRemainingArgsCount() > 0)) {
             profileFile = getNextArgRequired();
             fd = openFileForSystem(profileFile, "w");
             if (fd == null) {
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index dda48ad..79a0d73 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1990,7 +1990,7 @@
     }
 
     @GuardedBy("mProfilerLock")
-    private void stopProfilerLPf(ProcessRecord proc, int profileType) {
+    private void stopProfilerLPf(ProcessRecord proc, ProfilerInfo profilerInfo, int profileType) {
         if (proc == null || proc == mProfileData.getProfileProc()) {
             proc = mProfileData.getProfileProc();
             profileType = mProfileType;
@@ -2004,7 +2004,7 @@
             return;
         }
         try {
-            thread.profilerControl(false, null, profileType);
+            thread.profilerControl(false, profilerInfo, profileType);
         } catch (RemoteException e) {
             throw new IllegalStateException("Process disappeared");
         }
@@ -2039,41 +2039,58 @@
             ProfilerInfo profilerInfo, int profileType) {
         try {
             if (start) {
-                stopProfilerLPf(null, 0);
+                boolean needsFile = (profileType == ProfilerInfo.PROFILE_TYPE_REGULAR);
+                stopProfilerLPf(null, null, 0);
                 mService.setProfileApp(proc.info, proc.processName, profilerInfo,
-                        proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null);
+                        proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null, profileType);
                 mProfileData.setProfileProc(proc);
                 mProfileType = profileType;
-                ParcelFileDescriptor fd = profilerInfo.profileFd;
-                try {
-                    fd = fd.dup();
-                } catch (IOException e) {
-                    fd = null;
-                }
-                profilerInfo.profileFd = fd;
-                proc.mProfile.getThread().profilerControl(start, profilerInfo, profileType);
-                fd = null;
-                try {
-                    mProfileData.getProfilerInfo().profileFd.close();
-                } catch (IOException e) {
-                }
-                mProfileData.getProfilerInfo().profileFd = null;
 
-                if (proc.getPid() == mService.MY_PID) {
-                    // When profiling the system server itself, avoid closing the file
-                    // descriptor, as profilerControl will not create a copy.
-                    // Note: it is also not correct to just set profileFd to null, as the
-                    //       whole ProfilerInfo instance is passed down!
-                    profilerInfo = null;
-                }
-            } else {
-                stopProfilerLPf(proc, profileType);
-                if (profilerInfo != null && profilerInfo.profileFd != null) {
+                ParcelFileDescriptor fd = null;
+                if (needsFile) {
+                    fd = profilerInfo.profileFd;
                     try {
-                        profilerInfo.profileFd.close();
+                        fd = fd.dup();
+                    } catch (IOException e) {
+                        fd = null;
+                    }
+                    profilerInfo.profileFd = fd;
+                }
+
+                proc.mProfile.getThread().profilerControl(start, profilerInfo, profileType);
+
+                if (needsFile) {
+                    fd = null;
+                    try {
+                        mProfileData.getProfilerInfo().profileFd.close();
                     } catch (IOException e) {
                     }
+                    mProfileData.getProfilerInfo().profileFd = null;
+
+                    if (proc.getPid() == mService.MY_PID) {
+                        // When profiling the system server itself, avoid closing the file
+                        // descriptor, as profilerControl will not create a copy.
+                        // Note: it is also not correct to just set profileFd to null, as the
+                        //       whole ProfilerInfo instance is passed down!
+                        profilerInfo = null;
+                    }
                 }
+            } else {
+                boolean mayNeedFile = (profileType == ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD);
+                if (profilerInfo != null && profilerInfo.profileFd != null) {
+                    ParcelFileDescriptor fd = profilerInfo.profileFd;
+                    try {
+                        if (mayNeedFile) {
+                            fd = fd.dup();
+                        } else {
+                            fd.close();
+                        }
+                    } catch (IOException e) {
+                        fd = null;
+                    }
+                    profilerInfo.profileFd = fd;
+                }
+                stopProfilerLPf(proc, profilerInfo, profileType);
             }
 
             return true;
@@ -2090,7 +2107,7 @@
     }
 
     @GuardedBy("mProfilerLock")
-    void setProfileAppLPf(String processName, ProfilerInfo profilerInfo) {
+    void setProfileAppLPf(String processName, ProfilerInfo profilerInfo, int profileType) {
         mProfileData.setProfileApp(processName);
 
         if (mProfileData.getProfilerInfo() != null) {
@@ -2101,8 +2118,10 @@
                 }
             }
         }
-        mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
-        mProfileType = 0;
+        if (profilerInfo != null) {
+            mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
+        }
+        mProfileType = profileType;
     }
 
     @GuardedBy("mProfilerLock")
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 90f92b0..f79256d 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -39,7 +39,6 @@
 import android.aconfigd.Aconfigd.StorageReturnMessage;
 import android.aconfigd.Aconfigd.StorageReturnMessages;
 import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
-import static com.android.aconfig.flags.Flags.enableSystemAconfigdRust;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -392,8 +391,7 @@
     static ProtoInputStream sendAconfigdRequests(ProtoOutputStream requests) {
         // connect to aconfigd socket
         LocalSocket client = new LocalSocket();
-        String socketName = enableSystemAconfigdRust()
-                    ? "aconfigd_system" : "aconfigd";
+        String socketName = "aconfigd_system";
         try {
             client.connect(new LocalSocketAddress(
                 socketName, LocalSocketAddress.Namespace.RESERVED));
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 47a79a3..ca831d1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -61,6 +61,7 @@
 
 import android.Manifest;
 import android.annotation.AnyThread;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -186,6 +187,7 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.LocalServices;
+import com.android.server.art.ArtManagedInstallFileHelper;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.pkg.AndroidPackage;
@@ -848,7 +850,11 @@
             if (file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
             if (file.getName().endsWith(V4Signature.EXT)) return false;
             if (isAppMetadata(file)) return false;
-            if (DexMetadataHelper.isDexMetadataFile(file)) return false;
+            if (com.android.art.flags.Flags.artServiceV3()) {
+                if (ArtManagedInstallFileHelper.isArtManaged(file.getPath())) return false;
+            } else {
+                if (DexMetadataHelper.isDexMetadataFile(file)) return false;
+            }
             if (VerityUtils.isFsveritySignatureFile(file)) return false;
             if (ApkChecksums.isDigestOrDigestSignatureFile(file)) return false;
             return true;
@@ -872,6 +878,13 @@
             return true;
         }
     };
+    private static final FileFilter sArtManagedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            return !file.isDirectory() && com.android.art.flags.Flags.artServiceV3()
+                    && ArtManagedInstallFileHelper.isArtManaged(file.getPath());
+        }
+    };
 
     static boolean isDataLoaderInstallation(SessionParams params) {
         return params.dataLoaderParams != null;
@@ -1586,6 +1599,19 @@
     }
 
     @GuardedBy("mLock")
+    private List<String> getArtManagedFilePathsLocked() {
+        String[] names = getNamesLocked();
+        ArrayList<String> result = new ArrayList<>(names.length);
+        for (String name : names) {
+            File file = new File(stageDir, name);
+            if (sArtManagedFilter.accept(file)) {
+                result.add(file.getPath());
+            }
+        }
+        return result;
+    }
+
+    @GuardedBy("mLock")
     private void enableFsVerityToAddedApksWithIdsig() throws PackageManagerException {
         try {
             List<File> files = getAddedApksLocked();
@@ -3377,7 +3403,7 @@
         }
 
         final File targetFile = new File(stageDir, targetName);
-        resolveAndStageFileLocked(addedFile, targetFile, null);
+        resolveAndStageFileLocked(addedFile, targetFile, null, List.of() /* artManagedFilePaths */);
         mResolvedBaseFile = targetFile;
 
         // Populate package name of the apex session
@@ -3470,6 +3496,7 @@
                     TextUtils.formatSimple("Session: %d. No packages staged in %s", sessionId,
                           stageDir.getAbsolutePath()));
         }
+        final List<String> artManagedFilePaths = getArtManagedFilePathsLocked();
 
         // Verify that all staged packages are internally consistent
         final ArraySet<String> stagedSplits = new ArraySet<>();
@@ -3526,7 +3553,8 @@
             final File targetFile = new File(stageDir, targetName);
             if (!isArchivedInstallation()) {
                 final File sourceFile = new File(apk.getPath());
-                resolveAndStageFileLocked(sourceFile, targetFile, apk.getSplitName());
+                resolveAndStageFileLocked(
+                        sourceFile, targetFile, apk.getSplitName(), artManagedFilePaths);
             }
 
             // Base is coming from session
@@ -3687,7 +3715,7 @@
             // Inherit base if not overridden.
             if (mResolvedBaseFile == null) {
                 mResolvedBaseFile = new File(appInfo.getBaseCodePath());
-                inheritFileLocked(mResolvedBaseFile);
+                inheritFileLocked(mResolvedBaseFile, artManagedFilePaths);
                 // Collect the requiredSplitTypes from base
                 CollectionUtils.addAll(requiredSplitTypes, existing.getBaseRequiredSplitTypes());
             } else if ((params.installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
@@ -3706,7 +3734,7 @@
                     final boolean splitRemoved = removeSplitList.contains(splitName);
                     final boolean splitReplaced = stagedSplits.contains(splitName);
                     if (!splitReplaced && !splitRemoved) {
-                        inheritFileLocked(splitFile);
+                        inheritFileLocked(splitFile, artManagedFilePaths);
                         // Collect the requiredSplitTypes and staged splitTypes from splits
                         CollectionUtils.addAll(requiredSplitTypes,
                                 existing.getRequiredSplitTypes()[i]);
@@ -3892,6 +3920,23 @@
                 DexMetadataHelper.isFsVerityRequired());
     }
 
+    @FlaggedApi(com.android.art.flags.Flags.FLAG_ART_SERVICE_V3)
+    @GuardedBy("mLock")
+    private void maybeStageArtManagedInstallFilesLocked(File origFile, File targetFile,
+            List<String> artManagedFilePaths) throws PackageManagerException {
+        for (String path : ArtManagedInstallFileHelper.filterPathsForApk(
+                     artManagedFilePaths, origFile.getPath())) {
+            File artManagedFile = new File(path);
+            if (!FileUtils.isValidExtFilename(artManagedFile.getName())) {
+                throw new PackageManagerException(
+                        INSTALL_FAILED_INVALID_APK, "Invalid filename: " + artManagedFile);
+            }
+            File targetArtManagedFile = new File(
+                    ArtManagedInstallFileHelper.getTargetPathForApk(path, targetFile.getPath()));
+            stageFileLocked(artManagedFile, targetArtManagedFile);
+        }
+    }
+
     private IncrementalFileStorages getIncrementalFileStorages() {
         synchronized (mLock) {
             return mIncrementalFileStorages;
@@ -3989,8 +4034,8 @@
     }
 
     @GuardedBy("mLock")
-    private void resolveAndStageFileLocked(File origFile, File targetFile, String splitName)
-            throws PackageManagerException {
+    private void resolveAndStageFileLocked(File origFile, File targetFile, String splitName,
+            List<String> artManagedFilePaths) throws PackageManagerException {
         stageFileLocked(origFile, targetFile);
 
         // Stage APK's fs-verity signature if present.
@@ -4001,8 +4046,13 @@
                 && VerityUtils.isFsVeritySupported()) {
             maybeStageV4SignatureLocked(origFile, targetFile);
         }
-        // Stage dex metadata (.dm) and corresponding fs-verity signature if present.
-        maybeStageDexMetadataLocked(origFile, targetFile);
+        // Stage ART managed install files (e.g., dex metadata (.dm)) and corresponding fs-verity
+        // signature if present.
+        if (com.android.art.flags.Flags.artServiceV3()) {
+            maybeStageArtManagedInstallFilesLocked(origFile, targetFile, artManagedFilePaths);
+        } else {
+            maybeStageDexMetadataLocked(origFile, targetFile);
+        }
         // Stage checksums (.digests) if present.
         maybeStageDigestsLocked(origFile, targetFile, splitName);
     }
@@ -4027,7 +4077,7 @@
     }
 
     @GuardedBy("mLock")
-    private void inheritFileLocked(File origFile) {
+    private void inheritFileLocked(File origFile, List<String> artManagedFilePaths) {
         mResolvedInheritedFiles.add(origFile);
 
         maybeInheritFsveritySignatureLocked(origFile);
@@ -4035,12 +4085,20 @@
             maybeInheritV4SignatureLocked(origFile);
         }
 
-        // Inherit the dex metadata if present.
-        final File dexMetadataFile =
-                DexMetadataHelper.findDexMetadataForFile(origFile);
-        if (dexMetadataFile != null) {
-            mResolvedInheritedFiles.add(dexMetadataFile);
-            maybeInheritFsveritySignatureLocked(dexMetadataFile);
+        // Inherit ART managed install files (e.g., dex metadata (.dm)) if present.
+        if (com.android.art.flags.Flags.artServiceV3()) {
+            for (String path : ArtManagedInstallFileHelper.filterPathsForApk(
+                         artManagedFilePaths, origFile.getPath())) {
+                File artManagedFile = new File(path);
+                mResolvedInheritedFiles.add(artManagedFile);
+                maybeInheritFsveritySignatureLocked(artManagedFile);
+            }
+        } else {
+            final File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(origFile);
+            if (dexMetadataFile != null) {
+                mResolvedInheritedFiles.add(dexMetadataFile);
+                maybeInheritFsveritySignatureLocked(dexMetadataFile);
+            }
         }
         // Inherit the digests if present.
         final File digestsFile = ApkChecksums.findDigestsForFile(origFile);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
index 644ae47..1ba202b 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
@@ -29,8 +29,6 @@
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
-import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.DeviceConfig;
 
 import androidx.test.InstrumentationRegistry;
@@ -59,13 +57,8 @@
 @LargeTest
 @android.platform.test.annotations.DisabledOnRavenwood(reason = "Integration test")
 public class CpuPowerStatsCollectorValidationTest {
-    @Rule(order = 0)
-    public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Rule(order = 1)
-    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
-            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
-            : DeviceFlagsValueProvider.createCheckFlagsRule();
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private static final int WORK_DURATION_MS = 2000;
     private static final String TEST_PKG = "com.android.coretests.apps.bstatstestapp";
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
index ef0b570..1ff347f 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
@@ -31,8 +31,6 @@
 import android.platform.test.annotations.RequiresFlagsDisabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
-import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 
@@ -58,18 +56,13 @@
 @SuppressWarnings("GuardedBy")
 public class SystemServicePowerCalculatorTest {
     @Rule(order = 0)
-    public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Rule(order = 1)
-    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
-            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
-            : DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private static final double PRECISION = 0.000001;
     private static final int APP_UID1 = 100;
     private static final int APP_UID2 = 200;
 
-    @Rule(order = 2)
+    @Rule(order = 1)
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
             .setAveragePower(PowerProfile.POWER_CPU_ACTIVE, 720)
             .setCpuScalingPolicy(0, new int[]{0, 1}, new int[]{100, 200})