Merge changes from topic "mpietal_scrimcontroller" into main

* changes:
  Remove dreaming hosted lockscreen - Part #1
  Remove legacy ambient wallpaper support
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 0080a8d..1ae9ada 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -110,6 +110,7 @@
         "hwui_flags_java_lib",
         "interaction_jank_monitor_flags_lib",
         "libcore_exported_aconfig_flags_lib",
+        "libcore_readonly_aconfig_flags_lib",
         "libgui_flags_java_lib",
         "power_flags_lib",
         "sdk_sandbox_flags_lib",
@@ -169,6 +170,26 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// See b/368409430 - This is for libcore flags to be generated with
+// force-read-only mode, so access to the flags does not involve I/O,
+// which could break Isolated Processes with I/O permission disabled.
+// The issue will be addressed once new Aconfig storage API is landed
+// and the readonly version will be removed.
+aconfig_declarations {
+    name: "libcore-readonly-aconfig-flags",
+    package: "com.android.libcore.readonly",
+    container: "system",
+    srcs: ["libcore-readonly.aconfig"],
+}
+
+// Core Libraries / libcore
+java_aconfig_library {
+    name: "libcore_readonly_aconfig_flags_lib",
+    aconfig_declarations: "libcore-readonly-aconfig-flags",
+    mode: "force-read-only",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Telecom
 java_aconfig_library {
     name: "telecom_flags_core_java_lib",
diff --git a/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl b/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl
deleted file mode 100644
index 38a7956..0000000
--- a/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.verify.pkg;
-
-import android.content.pm.verify.pkg.VerificationStatus;
-import android.os.PersistableBundle;
-
-/**
- * Oneway interface that allows the verifier to send response or verification results back to
- * the system.
- * @hide
- */
-oneway interface IVerificationSessionCallback {
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
-    void reportVerificationIncomplete(int verificationId, int reason);
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
-    void reportVerificationComplete(int verificationId, in VerificationStatus status);
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
-    void reportVerificationCompleteWithExtensionResponse(int verificationId, in VerificationStatus status, in PersistableBundle response);
-}
diff --git a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
index 036c1e6..66caf2d 100644
--- a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
+++ b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
@@ -16,8 +16,11 @@
 
 package android.content.pm.verify.pkg;
 
+import android.content.pm.verify.pkg.VerificationStatus;
+import android.os.PersistableBundle;
+
 /**
- * Non-oneway interface that allows the verifier to retrieve information from the system.
+ * Non-oneway interface that allows the verifier to communicate with the system.
  * @hide
  */
 interface IVerificationSessionInterface {
@@ -27,4 +30,10 @@
     long extendTimeRemaining(int verificationId, long additionalMs);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
     boolean setVerificationPolicy(int verificationId, int policy);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
+    void reportVerificationIncomplete(int verificationId, int reason);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
+    void reportVerificationComplete(int verificationId, in VerificationStatus status);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
+    void reportVerificationCompleteWithExtensionResponse(int verificationId, in VerificationStatus status, in PersistableBundle response);
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/verify/pkg/VerificationSession.java b/core/java/android/content/pm/verify/pkg/VerificationSession.java
index f393be8..4ade211 100644
--- a/core/java/android/content/pm/verify/pkg/VerificationSession.java
+++ b/core/java/android/content/pm/verify/pkg/VerificationSession.java
@@ -79,8 +79,6 @@
     private final PersistableBundle mExtensionParams;
     @NonNull
     private final IVerificationSessionInterface mSession;
-    @NonNull
-    private final IVerificationSessionCallback mCallback;
     /**
      * The current policy that is active for the session. It might not be
      * the same as the original policy that was initially assigned for this verification session,
@@ -100,8 +98,7 @@
             @NonNull List<SharedLibraryInfo> declaredLibraries,
             @NonNull PersistableBundle extensionParams,
             @PackageInstaller.VerificationPolicy int defaultPolicy,
-            @NonNull IVerificationSessionInterface session,
-            @NonNull IVerificationSessionCallback callback) {
+            @NonNull IVerificationSessionInterface session) {
         mId = id;
         mInstallSessionId = installSessionId;
         mPackageName = packageName;
@@ -111,7 +108,6 @@
         mExtensionParams = extensionParams;
         mVerificationPolicy = defaultPolicy;
         mSession = session;
-        mCallback = callback;
     }
 
     /**
@@ -236,7 +232,7 @@
     @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
     public void reportVerificationIncomplete(@VerificationIncompleteReason int reason) {
         try {
-            mCallback.reportVerificationIncomplete(mId, reason);
+            mSession.reportVerificationIncomplete(mId, reason);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -250,7 +246,7 @@
     @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
     public void reportVerificationComplete(@NonNull VerificationStatus status) {
         try {
-            mCallback.reportVerificationComplete(mId, status);
+            mSession.reportVerificationComplete(mId, status);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -265,7 +261,7 @@
     public void reportVerificationComplete(@NonNull VerificationStatus status,
             @NonNull PersistableBundle response) {
         try {
-            mCallback.reportVerificationCompleteWithExtensionResponse(mId, status, response);
+            mSession.reportVerificationCompleteWithExtensionResponse(mId, status, response);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -281,7 +277,6 @@
         mExtensionParams = in.readPersistableBundle(getClass().getClassLoader());
         mVerificationPolicy = in.readInt();
         mSession = IVerificationSessionInterface.Stub.asInterface(in.readStrongBinder());
-        mCallback = IVerificationSessionCallback.Stub.asInterface(in.readStrongBinder());
     }
 
     @Override
@@ -300,7 +295,6 @@
         dest.writePersistableBundle(mExtensionParams);
         dest.writeInt(mVerificationPolicy);
         dest.writeStrongBinder(mSession.asBinder());
-        dest.writeStrongBinder(mCallback.asBinder());
     }
 
     @NonNull
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 8c87ad3..9395844 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -283,7 +283,7 @@
     private static NativeAllocationRegistry getRegistry(long size) {
         final long func = nGetNativeFinalizer();
         final Class cls = HardwareBuffer.class;
-        return com.android.libcore.Flags.nativeMetrics()
+        return com.android.libcore.readonly.Flags.nativeMetrics()
             ? NativeAllocationRegistry.createNonmalloced(cls, func, size)
             : NativeAllocationRegistry.createNonmalloced(cls.getClassLoader(), func, size);
     }
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 6a2daea..73a74b2 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -73,6 +73,9 @@
 
     private static final int ZYGOTE_CONNECT_TIMEOUT_MS = 60000;
 
+    // How long we wait for an AppZygote to complete pre-loading; this is a pretty conservative
+    // value that we can probably decrease over time, but we want to be careful here.
+    public static volatile int sAppZygotePreloadTimeoutMs = 15000;
     /**
      * Use a relatively short delay, because for app zygote, this is in the critical path of
      * service launch.
@@ -1100,31 +1103,52 @@
     }
 
     /**
+     * Updates the timeout used when preloading code in the app-zygote
+     *
+     * @param timeoutMs timeout in milliseconds
+     */
+    public static void setAppZygotePreloadTimeout(int timeoutMs) {
+        Slog.i(LOG_TAG, "Changing app-zygote preload timeout to " + timeoutMs + " ms.");
+
+        sAppZygotePreloadTimeoutMs = timeoutMs;
+    }
+
+    /**
      * Instructs the zygote to pre-load the application code for the given Application.
      * Only the app zygote supports this function.
      */
     public boolean preloadApp(ApplicationInfo appInfo, String abi)
             throws ZygoteStartFailedEx, IOException {
         synchronized (mLock) {
+            int ret;
             ZygoteState state = openZygoteSocketIfNeeded(abi);
-            state.mZygoteOutputWriter.write("2");
-            state.mZygoteOutputWriter.newLine();
+            int previousSocketTimeout = state.mZygoteSessionSocket.getSoTimeout();
 
-            state.mZygoteOutputWriter.write("--preload-app");
-            state.mZygoteOutputWriter.newLine();
+            try {
+                state.mZygoteSessionSocket.setSoTimeout(sAppZygotePreloadTimeoutMs);
 
-            // Zygote args needs to be strings, so in order to pass ApplicationInfo,
-            // write it to a Parcel, and base64 the raw Parcel bytes to the other side.
-            Parcel parcel = Parcel.obtain();
-            appInfo.writeToParcel(parcel, 0 /* flags */);
-            String encodedParcelData = Base64.getEncoder().encodeToString(parcel.marshall());
-            parcel.recycle();
-            state.mZygoteOutputWriter.write(encodedParcelData);
-            state.mZygoteOutputWriter.newLine();
+                state.mZygoteOutputWriter.write("2");
+                state.mZygoteOutputWriter.newLine();
 
-            state.mZygoteOutputWriter.flush();
+                state.mZygoteOutputWriter.write("--preload-app");
+                state.mZygoteOutputWriter.newLine();
 
-            return (state.mZygoteInputStream.readInt() == 0);
+                // Zygote args needs to be strings, so in order to pass ApplicationInfo,
+                // write it to a Parcel, and base64 the raw Parcel bytes to the other side.
+                Parcel parcel = Parcel.obtain();
+                appInfo.writeToParcel(parcel, 0 /* flags */);
+                String encodedParcelData = Base64.getEncoder().encodeToString(parcel.marshall());
+                parcel.recycle();
+                state.mZygoteOutputWriter.write(encodedParcelData);
+                state.mZygoteOutputWriter.newLine();
+
+                state.mZygoteOutputWriter.flush();
+
+                ret = state.mZygoteInputStream.readInt();
+            } finally {
+                state.mZygoteSessionSocket.setSoTimeout(previousSocketTimeout);
+            }
+            return ret == 0;
         }
     }
 
diff --git a/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java b/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
index 80255c5..90ae306 100644
--- a/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
+++ b/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
@@ -33,7 +33,6 @@
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.SigningInfo;
 import android.content.pm.VersionedPackage;
-import android.content.pm.verify.pkg.IVerificationSessionCallback;
 import android.content.pm.verify.pkg.IVerificationSessionInterface;
 import android.content.pm.verify.pkg.VerificationSession;
 import android.content.pm.verify.pkg.VerificationStatus;
@@ -84,8 +83,6 @@
     private final PersistableBundle mTestExtensionParams = new PersistableBundle();
     @Mock
     private IVerificationSessionInterface mTestSessionInterface;
-    @Mock
-    private IVerificationSessionCallback mTestCallback;
     private VerificationSession mTestSession;
 
     @Before
@@ -96,7 +93,7 @@
         mTestExtensionParams.putString(TEST_KEY, TEST_VALUE);
         mTestSession = new VerificationSession(TEST_ID, TEST_INSTALL_SESSION_ID,
                 TEST_PACKAGE_NAME, TEST_PACKAGE_URI, TEST_SIGNING_INFO, mTestDeclaredLibraries,
-                mTestExtensionParams, TEST_POLICY, mTestSessionInterface, mTestCallback);
+                mTestExtensionParams, TEST_POLICY, mTestSessionInterface);
     }
 
     @Test
@@ -138,25 +135,22 @@
         assertThat(mTestSession.extendTimeRemaining(TEST_EXTEND_TIME)).isEqualTo(TEST_EXTEND_TIME);
         verify(mTestSessionInterface, times(1)).extendTimeRemaining(
                 eq(TEST_ID), eq(TEST_EXTEND_TIME));
-    }
 
-    @Test
-    public void testCallback() throws Exception {
         PersistableBundle response = new PersistableBundle();
         response.putString("test key", "test value");
         final VerificationStatus status =
                 new VerificationStatus.Builder().setVerified(true).build();
         mTestSession.reportVerificationComplete(status);
-        verify(mTestCallback, times(1)).reportVerificationComplete(
+        verify(mTestSessionInterface, times(1)).reportVerificationComplete(
                 eq(TEST_ID), eq(status));
         mTestSession.reportVerificationComplete(status, response);
-        verify(mTestCallback, times(1))
+        verify(mTestSessionInterface, times(1))
                 .reportVerificationCompleteWithExtensionResponse(
                         eq(TEST_ID), eq(status), eq(response));
 
         final int reason = VerificationSession.VERIFICATION_INCOMPLETE_UNKNOWN;
         mTestSession.reportVerificationIncomplete(reason);
-        verify(mTestCallback, times(1)).reportVerificationIncomplete(
+        verify(mTestSessionInterface, times(1)).reportVerificationIncomplete(
                 eq(TEST_ID), eq(reason));
     }
 
diff --git a/core/tests/coretests/src/android/content/pm/verify/VerifierServiceTest.java b/core/tests/coretests/src/android/content/pm/verify/VerifierServiceTest.java
index 7807c8a..56fc66a 100644
--- a/core/tests/coretests/src/android/content/pm/verify/VerifierServiceTest.java
+++ b/core/tests/coretests/src/android/content/pm/verify/VerifierServiceTest.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.SigningInfo;
+import android.content.pm.verify.pkg.IVerificationSessionInterface;
 import android.content.pm.verify.pkg.IVerifierService;
 import android.content.pm.verify.pkg.VerificationSession;
 import android.content.pm.verify.pkg.VerifierService;
@@ -63,7 +64,8 @@
         mService = Mockito.mock(VerifierService.class, Answers.CALLS_REAL_METHODS);
         mSession = new VerificationSession(TEST_ID, TEST_INSTALL_SESSION_ID,
                 TEST_PACKAGE_NAME, TEST_PACKAGE_URI, TEST_SIGNING_INFO,
-                new ArrayList<>(), new PersistableBundle(), TEST_POLICY, null, null);
+                new ArrayList<>(), new PersistableBundle(), TEST_POLICY, Mockito.mock(
+                IVerificationSessionInterface.class));
     }
 
     @Test
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6d31578..461a5ae 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -128,6 +128,22 @@
     private static final WeakHashMap<Bitmap, Void> sAllBitmaps = new WeakHashMap<>();
 
     /**
+     * @hide
+     */
+    private static NativeAllocationRegistry getRegistry(boolean malloc, long size) {
+        final long free = nativeGetNativeFinalizer();
+        if (com.android.libcore.readonly.Flags.nativeMetrics()) {
+            Class cls = Bitmap.class;
+            return malloc ? NativeAllocationRegistry.createMalloced(cls, free, size)
+                          : NativeAllocationRegistry.createNonmalloced(cls, free, size);
+        } else {
+            ClassLoader loader = Bitmap.class.getClassLoader();
+            return malloc ? NativeAllocationRegistry.createMalloced(loader, free, size)
+                          : NativeAllocationRegistry.createNonmalloced(loader, free, size);
+        }
+    }
+
+    /**
      * Private constructor that must receive an already allocated native bitmap
      * int (pointer).
      */
@@ -151,7 +167,6 @@
         mWidth = width;
         mHeight = height;
         mRequestPremultiplied = requestPremultiplied;
-
         mNinePatchChunk = ninePatchChunk;
         mNinePatchInsets = ninePatchInsets;
         if (density >= 0) {
@@ -159,17 +174,9 @@
         }
 
         mNativePtr = nativeBitmap;
-
         final int allocationByteCount = getAllocationByteCount();
-        NativeAllocationRegistry registry;
-        if (fromMalloc) {
-            registry = NativeAllocationRegistry.createMalloced(
-                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
-        } else {
-            registry = NativeAllocationRegistry.createNonmalloced(
-                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
-        }
-        registry.registerNativeAllocation(this, nativeBitmap);
+        getRegistry(fromMalloc, allocationByteCount).registerNativeAllocation(this, mNativePtr);
+
         synchronized (Bitmap.class) {
           sAllBitmaps.put(this, null);
         }
diff --git a/libcore-readonly.aconfig b/libcore-readonly.aconfig
new file mode 100644
index 0000000..3cda92c
--- /dev/null
+++ b/libcore-readonly.aconfig
@@ -0,0 +1,25 @@
+package: "com.android.libcore.readonly"
+container: "system"
+
+# These are the read-only version of the aconfig flags in com.android.libcore
+# that will be built with 'force-read-only' mode.
+# See b/368409430 - these flags will be removed once the new aconfig API landed.
+flag {
+    namespace: "core_libraries"
+    name: "post_cleanup_apis"
+    is_exported: false
+    description: "This flag includes APIs to add/remove/call callbacks post-cleanup"
+    bug: "331243037"
+    # APIs provided by a mainline module can only use a frozen flag.
+    is_fixed_read_only: true
+}
+
+flag {
+    namespace: "core_libraries"
+    name: "native_metrics"
+    is_exported: false
+    description: "This flag includes APIs fo maintaining and exposing native allocation metrics"
+    bug: "331243037"
+    # APIs provided by a mainline module can only use a frozen flag.
+    is_fixed_read_only: true
+}
diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index 2983875..d75318f 100644
--- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -324,7 +324,7 @@
                 mOffHostName = sa.getString(
                         com.android.internal.R.styleable.OffHostApduService_secureElementName);
                 mShouldDefaultToObserveMode = sa.getBoolean(
-                        R.styleable.HostApduService_shouldDefaultToObserveMode,
+                        R.styleable.OffHostApduService_shouldDefaultToObserveMode,
                         false);
                 if (mOffHostName != null) {
                     if (mOffHostName.equals("eSE")) {
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 8e884bc..d918201 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -124,6 +124,7 @@
     ],
     libs: [
         "framework-minus-apex.ravenwood",
+        "framework-configinfrastructure.ravenwood",
         "ravenwood-helper-libcore-runtime",
     ],
     sdk_version: "core_current",
@@ -395,6 +396,9 @@
         "icu4j-icudata-jarjar",
         "icu4j-icutzdata-jarjar",
 
+        // DeviceConfig
+        "framework-configinfrastructure.ravenwood",
+
         // Provide runtime versions of utils linked in below
         "junit",
         "truth",
diff --git a/ravenwood/Framework.bp b/ravenwood/Framework.bp
index 5cb1479..1bea434 100644
--- a/ravenwood/Framework.bp
+++ b/ravenwood/Framework.bp
@@ -290,3 +290,57 @@
         "core-icu4j-for-host.ravenwood.jar",
     ],
 }
+
+///////////////////////////////////
+// framework-configinfrastructure
+///////////////////////////////////
+
+java_genrule {
+    name: "framework-configinfrastructure.ravenwood-base",
+    tools: ["hoststubgen"],
+    cmd: "$(location hoststubgen) " +
+        "@$(location :ravenwood-standard-options) " +
+
+        "--debug-log $(location framework-configinfrastructure.log) " +
+        "--stats-file $(location framework-configinfrastructure_stats.csv) " +
+        "--supported-api-list-file $(location framework-configinfrastructure_apis.csv) " +
+        "--gen-keep-all-file $(location framework-configinfrastructure_keep_all.txt) " +
+        "--gen-input-dump-file $(location framework-configinfrastructure_dump.txt) " +
+
+        "--out-impl-jar $(location ravenwood.jar) " +
+        "--in-jar $(location :framework-configinfrastructure.impl{.jar}) " +
+
+        "--policy-override-file $(location :ravenwood-common-policies) " +
+        "--policy-override-file $(location :framework-configinfrastructure-ravenwood-policies) ",
+    srcs: [
+        ":framework-configinfrastructure.impl{.jar}",
+
+        ":ravenwood-common-policies",
+        ":framework-configinfrastructure-ravenwood-policies",
+        ":ravenwood-standard-options",
+    ],
+    out: [
+        "ravenwood.jar",
+
+        // Following files are created just as FYI.
+        "framework-configinfrastructure_keep_all.txt",
+        "framework-configinfrastructure_dump.txt",
+
+        "framework-configinfrastructure.log",
+        "framework-configinfrastructure_stats.csv",
+        "framework-configinfrastructure_apis.csv",
+    ],
+    visibility: ["//visibility:private"],
+}
+
+java_genrule {
+    name: "framework-configinfrastructure.ravenwood",
+    defaults: ["ravenwood-internal-only-visibility-genrule"],
+    cmd: "cp $(in) $(out)",
+    srcs: [
+        ":framework-configinfrastructure.ravenwood-base{ravenwood.jar}",
+    ],
+    out: [
+        "framework-configinfrastructure.ravenwood.jar",
+    ],
+}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index afa7a6c..e2d73d1 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -40,6 +40,7 @@
 import android.os.Looper;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.provider.DeviceConfig_host;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.Log;
@@ -333,6 +334,8 @@
         }
         android.os.Process.reset$ravenwood();
 
+        DeviceConfig_host.reset();
+
         try {
             ResourcesManager.setInstance(null); // Better structure needed.
         } catch (Exception e) {
diff --git a/ravenwood/runtime-helper-src/framework/android/provider/DeviceConfig_host.java b/ravenwood/runtime-helper-src/framework/android/provider/DeviceConfig_host.java
new file mode 100644
index 0000000..9c2188f
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/android/provider/DeviceConfig_host.java
@@ -0,0 +1,33 @@
+/*
+ * 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.provider;
+
+public class DeviceConfig_host {
+
+    /**
+     * Called by Ravenwood runtime to reset all local changes.
+     */
+    public static void reset() {
+        RavenwoodConfigDataStore.getInstance().clearAll();
+    }
+
+    /**
+     * Called by {@link DeviceConfig#newDataStore()}
+     */
+    public static DeviceConfigDataStore newDataStore() {
+        return RavenwoodConfigDataStore.getInstance();
+    }
+}
diff --git a/ravenwood/runtime-helper-src/framework/android/provider/RavenwoodConfigDataStore.java b/ravenwood/runtime-helper-src/framework/android/provider/RavenwoodConfigDataStore.java
new file mode 100644
index 0000000..4bc3de7
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/android/provider/RavenwoodConfigDataStore.java
@@ -0,0 +1,253 @@
+/*
+ * 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.provider;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.DeviceConfig.BadConfigException;
+import android.provider.DeviceConfig.MonitorCallback;
+import android.provider.DeviceConfig.Properties;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * {@link DeviceConfigDataStore} used only on Ravenwood.
+ *
+ * TODO(b/368591527) Support monitor callback related features
+ * TODO(b/368591527) Support "default" related features
+ */
+final class RavenwoodConfigDataStore implements DeviceConfigDataStore {
+    private static final RavenwoodConfigDataStore sInstance = new RavenwoodConfigDataStore();
+
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private int mSyncDisabledMode = DeviceConfig.SYNC_DISABLED_MODE_NONE;
+
+    @GuardedBy("mLock")
+    private final HashMap<String, HashMap<String, String>> mStore = new HashMap<>();
+
+    private record ObserverInfo(String namespace, ContentObserver observer) {
+    }
+
+    @GuardedBy("mLock")
+    private final ArrayList<ObserverInfo> mObservers = new ArrayList<>();
+
+    static RavenwoodConfigDataStore getInstance() {
+        return sInstance;
+    }
+
+    private static void shouldNotBeCalled() {
+        throw new RuntimeException("shouldNotBeCalled");
+    }
+
+    void clearAll() {
+        synchronized (mLock) {
+            mSyncDisabledMode = DeviceConfig.SYNC_DISABLED_MODE_NONE;
+            mStore.clear();
+        }
+    }
+
+    @GuardedBy("mLock")
+    private HashMap<String, String> getNamespaceLocked(@NonNull String namespace) {
+        Objects.requireNonNull(namespace);
+        return mStore.computeIfAbsent(namespace, k -> new HashMap<>());
+    }
+
+    /** {@inheritDoc} */
+    @NonNull
+    @Override
+    public Map<String, String> getAllProperties() {
+        synchronized (mLock) {
+            var ret = new HashMap<String, String>();
+
+            for (var namespaceAndMap : mStore.entrySet()) {
+                for (var nameAndValue : namespaceAndMap.getValue().entrySet()) {
+                    ret.put(namespaceAndMap.getKey() + "/" + nameAndValue.getKey(),
+                            nameAndValue.getValue());
+                }
+            }
+            return ret;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @NonNull
+    @Override
+    public Properties getProperties(@NonNull String namespace, @NonNull String... names) {
+        Objects.requireNonNull(namespace);
+
+        synchronized (mLock) {
+            var namespaceMap = getNamespaceLocked(namespace);
+
+            if (names.length == 0) {
+                return new Properties(namespace, Map.copyOf(namespaceMap));
+            } else {
+                var map = new HashMap<String, String>();
+                for (var name : names) {
+                    Objects.requireNonNull(name);
+                    map.put(name, namespaceMap.get(name));
+                }
+                return new Properties(namespace, map);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean setProperties(@NonNull Properties properties) throws BadConfigException {
+        Objects.requireNonNull(properties);
+
+        synchronized (mLock) {
+            var namespaceMap = getNamespaceLocked(properties.getNamespace());
+            for (var kv : properties.getPropertyValues().entrySet()) {
+                namespaceMap.put(
+                        Objects.requireNonNull(kv.getKey()),
+                        Objects.requireNonNull(kv.getValue())
+                );
+            }
+            notifyObserversLock(properties.getNamespace(),
+                    properties.getKeyset().toArray(new String[0]));
+        }
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean setProperty(@NonNull String namespace, @NonNull String name,
+            @Nullable String value, boolean makeDefault) {
+        Objects.requireNonNull(namespace);
+        Objects.requireNonNull(name);
+
+        synchronized (mLock) {
+            var namespaceMap = getNamespaceLocked(namespace);
+            namespaceMap.put(name, value);
+
+            // makeDefault not supported.
+            notifyObserversLock(namespace, new String[]{name});
+        }
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean deleteProperty(@NonNull String namespace, @NonNull String name) {
+        Objects.requireNonNull(namespace);
+        Objects.requireNonNull(name);
+
+        synchronized (mLock) {
+            var namespaceMap = getNamespaceLocked(namespace);
+            if (namespaceMap.remove(name) != null) {
+                notifyObserversLock(namespace, new String[]{name});
+            }
+        }
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void resetToDefaults(int resetMode, @Nullable String namespace) {
+        // not supported in DeviceConfig.java
+        shouldNotBeCalled();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setSyncDisabledMode(int syncDisabledMode) {
+        synchronized (mLock) {
+            mSyncDisabledMode = syncDisabledMode;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int getSyncDisabledMode() {
+        synchronized (mLock) {
+            return mSyncDisabledMode;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setMonitorCallback(@NonNull ContentResolver resolver, @NonNull Executor executor,
+            @NonNull MonitorCallback callback) {
+        // not supported in DeviceConfig.java
+        shouldNotBeCalled();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void clearMonitorCallback(@NonNull ContentResolver resolver) {
+        // not supported in DeviceConfig.java
+        shouldNotBeCalled();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void registerContentObserver(@NonNull String namespace, boolean notifyForescendants,
+            ContentObserver contentObserver) {
+        synchronized (mLock) {
+            mObservers.add(new ObserverInfo(
+                    Objects.requireNonNull(namespace),
+                    Objects.requireNonNull(contentObserver)
+            ));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void unregisterContentObserver(@NonNull ContentObserver contentObserver) {
+        synchronized (mLock) {
+            for (int i = mObservers.size() - 1; i >= 0; i--) {
+                if (mObservers.get(i).observer == contentObserver) {
+                    mObservers.remove(i);
+                }
+            }
+        }
+    }
+
+    private static final Uri CONTENT_URI = Uri.parse("content://settings/config");
+
+    @GuardedBy("mLock")
+    private void notifyObserversLock(@NonNull String namespace, String[] keys) {
+        var urib = CONTENT_URI.buildUpon().appendPath(namespace);
+        for (var key : keys) {
+            urib.appendEncodedPath(key);
+        }
+        var uri = urib.build();
+
+        final var copy = List.copyOf(mObservers);
+        new Handler(Looper.getMainLooper()).post(() -> {
+            for (int i = copy.size() - 1; i >= 0; i--) {
+                if (copy.get(i).namespace.equals(namespace)) {
+                    copy.get(i).observer.dispatchChange(false, uri);
+                }
+            }
+        });
+    }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 210301e..02e2c39 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -110,6 +110,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.ZygoteProcess;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -442,6 +443,8 @@
                     return runSetForegroundServiceDelegate(pw);
                 case "capabilities":
                     return runCapabilities(pw);
+                case "set-app-zygote-preload-timeout":
+                    return runSetAppZygotePreloadTimeout(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -451,6 +454,15 @@
         return -1;
     }
 
+    int runSetAppZygotePreloadTimeout(PrintWriter pw) throws RemoteException {
+        final String timeout = getNextArgRequired();
+        final int timeoutMs = Integer.parseInt(timeout);
+
+        ZygoteProcess.setAppZygotePreloadTimeout(timeoutMs);
+
+        return 0;
+    }
+
     int runCapabilities(PrintWriter pw) throws RemoteException {
         final PrintWriter err = getErrPrintWriter();
         boolean outputAsProtobuf = false;
@@ -4623,6 +4635,8 @@
             pw.println("  capabilities [--protobuf]");
             pw.println("         Output am supported features (text format). Options are:");
             pw.println("         --protobuf: format output using protobuffer");
+            pw.println("  set-app-zygote-preload-timeout <TIMEOUT_IN_MS>");
+            pw.println("         Set the timeout for preloading code in the app-zygote");
             Intent.printIntentArgsHelp(pw, "");
         }
     }
diff --git a/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
index b7cc7cce..0dd1f4c 100644
--- a/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
+++ b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
@@ -35,7 +35,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.SigningInfo;
-import android.content.pm.verify.pkg.IVerificationSessionCallback;
 import android.content.pm.verify.pkg.IVerificationSessionInterface;
 import android.content.pm.verify.pkg.IVerifierService;
 import android.content.pm.verify.pkg.VerificationSession;
@@ -45,7 +44,6 @@
 import android.os.Handler;
 import android.os.PersistableBundle;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.util.Pair;
@@ -307,8 +305,7 @@
                 /* id= */ verificationId,
                 /* installSessionId= */ installationSessionId,
                 packageName, stagedPackageUri, signingInfo, declaredLibraries, extensionParams,
-                verificationPolicy, new VerificationSessionInterface(callback),
-                new VerificationSessionCallback(callback));
+                verificationPolicy, new VerificationSessionInterface(callback));
         AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> {
             if (!retry) {
                 if (DEBUG) {
@@ -468,17 +465,9 @@
             }
             return mCallback.setVerificationPolicy(policy);
         }
-    }
-
-    private class VerificationSessionCallback extends IVerificationSessionCallback.Stub {
-        private final PackageInstallerSession.VerifierCallback mCallback;
-
-        VerificationSessionCallback(PackageInstallerSession.VerifierCallback callback) {
-            mCallback = callback;
-        }
 
         @Override
-        public void reportVerificationIncomplete(int id, int reason) throws RemoteException {
+        public void reportVerificationIncomplete(int id, int reason) {
             checkCallerPermission();
             final VerificationStatusTracker tracker;
             synchronized (mVerificationStatus) {
@@ -494,16 +483,14 @@
         }
 
         @Override
-        public void reportVerificationComplete(int id, VerificationStatus verificationStatus)
-                throws RemoteException {
+        public void reportVerificationComplete(int id, VerificationStatus verificationStatus) {
             reportVerificationCompleteWithExtensionResponse(id, verificationStatus,
                     /* extensionResponse= */ null);
         }
 
         @Override
         public void reportVerificationCompleteWithExtensionResponse(int id,
-                VerificationStatus verificationStatus, PersistableBundle extensionResponse)
-                throws RemoteException {
+                VerificationStatus verificationStatus, PersistableBundle extensionResponse) {
             checkCallerPermission();
             final VerificationStatusTracker tracker;
             synchronized (mVerificationStatus) {