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) {