Merge "[Ravenwood] Cleanup and update RavenwoodEnvironment" into main
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 30d2dec..3c3a4fd 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -36,8 +36,6 @@
import android.util.Slog;
import android.view.View;
-import com.android.internal.ravenwood.RavenwoodEnvironment;
-
import dalvik.system.VMRuntime;
import java.util.ArrayList;
@@ -51,10 +49,6 @@
*/
@RavenwoodKeepWholeClass
public class Build {
- static {
- // Set up the default system properties.
- RavenwoodEnvironment.ensureRavenwoodInitialized();
- }
private static final String TAG = "Build";
/** Value used for when a build property is unknown. */
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index e80efd2..60eeb2b 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -41,7 +41,6 @@
import android.net.Uri;
import android.os.MessageQueue.OnFileDescriptorEventListener;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodReplace;
import android.ravenwood.annotation.RavenwoodThrow;
import android.system.ErrnoException;
import android.system.Os;
@@ -51,8 +50,6 @@
import android.util.Log;
import android.util.Slog;
-import com.android.internal.ravenwood.RavenwoodEnvironment;
-
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
@@ -1254,15 +1251,10 @@
}
}
- @RavenwoodReplace
private static boolean isAtLeastQ() {
return (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q);
}
- private static boolean isAtLeastQ$ravenwood() {
- return RavenwoodEnvironment.workaround().isTargetSdkAtLeastQ();
- }
-
private static int ifAtLeastQ(int value) {
return isAtLeastQ() ? value : 0;
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index cd8788d..851953a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -29,6 +29,11 @@
import android.annotation.UptimeMillisLong;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build.VERSION_CODES;
+import android.ravenwood.annotation.RavenwoodKeep;
+import android.ravenwood.annotation.RavenwoodKeepPartialClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
import android.sysprop.MemoryProperties;
import android.system.ErrnoException;
import android.system.Os;
@@ -37,8 +42,6 @@
import android.util.Pair;
import android.webkit.WebViewZygote;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.util.Preconditions;
import com.android.sdksandbox.flags.Flags;
import dalvik.system.VMDebug;
@@ -55,6 +58,8 @@
/**
* Tools for managing OS processes.
*/
+@RavenwoodKeepPartialClass
+@RavenwoodRedirectionClass("Process_ravenwood")
public class Process {
private static final String LOG_TAG = "Process";
@@ -672,7 +677,6 @@
*/
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
-
/**
* The process name set via {@link #setArgV0(String)}.
*/
@@ -846,47 +850,20 @@
/**
* Returns true if the current process is a 64-bit runtime.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean is64Bit() {
return VMRuntime.getRuntime().is64Bit();
}
- private static volatile ThreadLocal<SomeArgs> sIdentity$ravenwood;
-
- /** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
- public static void init$ravenwood(final int uid, final int pid) {
- sIdentity$ravenwood = ThreadLocal.withInitial(() -> {
- final SomeArgs args = SomeArgs.obtain();
- args.argi1 = uid;
- args.argi2 = pid;
- args.argi3 = Long.hashCode(Thread.currentThread().getId());
- args.argi4 = THREAD_PRIORITY_DEFAULT;
- args.arg1 = Boolean.TRUE; // backgroundOk
- return args;
- });
- }
-
- /** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
- public static void reset$ravenwood() {
- sIdentity$ravenwood = null;
- }
-
/**
* Returns the identifier of this process, which can be used with
* {@link #killProcess} and {@link #sendSignal}.
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodKeep
public static final int myPid() {
return Os.getpid();
}
- /** @hide */
- public static final int myPid$ravenwood() {
- return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().argi2;
- }
-
/**
* Returns the identifier of this process' parent.
* @hide
@@ -900,39 +877,29 @@
* Returns the identifier of the calling thread, which be used with
* {@link #setThreadPriority(int, int)}.
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodKeep
public static final int myTid() {
return Os.gettid();
}
- /** @hide */
- public static final int myTid$ravenwood() {
- return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().argi3;
- }
-
/**
* Returns the identifier of this process's uid. This is the kernel uid
* that the process is running under, which is the identity of its
* app-specific sandbox. It is different from {@link #myUserHandle} in that
* a uid identifies a specific app sandbox in a specific user.
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodKeep
public static final int myUid() {
return Os.getuid();
}
- /** @hide */
- public static final int myUid$ravenwood() {
- return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().argi1;
- }
-
/**
* Returns this process's user handle. This is the
* user the process is running under. It is distinct from
* {@link #myUid()} in that a particular user will have multiple
* distinct apps running under it each with their own uid.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static UserHandle myUserHandle() {
return UserHandle.of(UserHandle.getUserId(myUid()));
}
@@ -941,7 +908,7 @@
* Returns whether the given uid belongs to a system core component or not.
* @hide
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static boolean isCoreUid(int uid) {
return UserHandle.isCore(uid);
}
@@ -952,7 +919,7 @@
* @return Whether the uid corresponds to an application sandbox running in
* a specific user.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static boolean isApplicationUid(int uid) {
return UserHandle.isApp(uid);
}
@@ -960,7 +927,7 @@
/**
* Returns whether the current process is in an isolated sandbox.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean isIsolated() {
return isIsolated(myUid());
}
@@ -972,7 +939,7 @@
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
publicAlternatives = "Use {@link #isIsolatedUid(int)} instead.")
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean isIsolated(int uid) {
return isIsolatedUid(uid);
}
@@ -980,7 +947,7 @@
/**
* Returns whether the process with the given {@code uid} is an isolated sandbox.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean isIsolatedUid(int uid) {
uid = UserHandle.getAppId(uid);
return (uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID)
@@ -992,7 +959,7 @@
* @see android.app.sdksandbox.SdkSandboxManager
*/
@SuppressLint("UnflaggedApi") // promoting from @SystemApi.
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean isSdkSandboxUid(int uid) {
uid = UserHandle.getAppId(uid);
return (uid >= FIRST_SDK_SANDBOX_UID && uid <= LAST_SDK_SANDBOX_UID);
@@ -1008,7 +975,7 @@
* @throws IllegalArgumentException if input is not an sdk sandbox uid
*/
@SuppressLint("UnflaggedApi") // promoting from @SystemApi.
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final int getAppUidForSdkSandboxUid(int uid) {
if (!isSdkSandboxUid(uid)) {
throw new IllegalArgumentException("Input UID is not an SDK sandbox UID");
@@ -1024,7 +991,7 @@
*/
@SystemApi(client = MODULE_LIBRARIES)
@TestApi
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
// TODO(b/318651609): Deprecate once Process#getSdkSandboxUidForAppUid is rolled out to 100%
public static final int toSdkSandboxUid(int uid) {
return uid + (FIRST_SDK_SANDBOX_UID - FIRST_APPLICATION_UID);
@@ -1040,7 +1007,7 @@
* @throws IllegalArgumentException if input is not an app uid
*/
@FlaggedApi(Flags.FLAG_SDK_SANDBOX_UID_TO_APP_UID_API)
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final int getSdkSandboxUidForAppUid(int uid) {
if (!isApplicationUid(uid)) {
throw new IllegalArgumentException("Input UID is not an app UID");
@@ -1051,7 +1018,7 @@
/**
* Returns whether the current process is a sdk sandbox process.
*/
- @android.ravenwood.annotation.RavenwoodKeep
+ @RavenwoodKeep
public static final boolean isSdkSandbox() {
return isSdkSandboxUid(myUid());
}
@@ -1128,28 +1095,11 @@
* not have permission to modify the given thread, or to use the given
* priority.
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodRedirect
public static final native void setThreadPriority(int tid,
@IntRange(from = -20, to = THREAD_PRIORITY_LOWEST) int priority)
throws IllegalArgumentException, SecurityException;
- /** @hide */
- public static final void setThreadPriority$ravenwood(int tid, int priority) {
- final SomeArgs args =
- Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get();
- if (args.argi3 == tid) {
- boolean backgroundOk = (args.arg1 == Boolean.TRUE);
- if (priority >= THREAD_PRIORITY_BACKGROUND && !backgroundOk) {
- throw new IllegalArgumentException(
- "Priority " + priority + " blocked by setCanSelfBackground()");
- }
- args.argi4 = priority;
- } else {
- throw new UnsupportedOperationException(
- "Cross-thread priority management not yet available in Ravenwood");
- }
- }
-
/**
* Call with 'false' to cause future calls to {@link #setThreadPriority(int)} to
* throw an exception if passed a background-level thread priority. This is only
@@ -1157,16 +1107,9 @@
*
* @hide
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodRedirect
public static final native void setCanSelfBackground(boolean backgroundOk);
- /** @hide */
- public static final void setCanSelfBackground$ravenwood(boolean backgroundOk) {
- final SomeArgs args =
- Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get();
- args.arg1 = Boolean.valueOf(backgroundOk);
- }
-
/**
* Sets the scheduling group for a thread.
* @hide
@@ -1295,13 +1238,12 @@
*
* @see #setThreadPriority(int, int)
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodReplace
public static final native void setThreadPriority(
@IntRange(from = -20, to = THREAD_PRIORITY_LOWEST) int priority)
throws IllegalArgumentException, SecurityException;
- /** @hide */
- public static final void setThreadPriority$ravenwood(int priority) {
+ private static void setThreadPriority$ravenwood(int priority) {
setThreadPriority(myTid(), priority);
}
@@ -1318,23 +1260,11 @@
* @throws IllegalArgumentException Throws IllegalArgumentException if
* <var>tid</var> does not exist.
*/
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodRedirect
@IntRange(from = -20, to = THREAD_PRIORITY_LOWEST)
public static final native int getThreadPriority(int tid)
throws IllegalArgumentException;
- /** @hide */
- public static final int getThreadPriority$ravenwood(int tid) {
- final SomeArgs args =
- Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get();
- if (args.argi3 == tid) {
- return args.argi4;
- } else {
- throw new UnsupportedOperationException(
- "Cross-thread priority management not yet available in Ravenwood");
- }
- }
-
/**
* Return the current scheduling policy of a thread, based on Linux.
*
diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
index 30b160a..a69d2e4 100644
--- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
+++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
@@ -28,19 +28,9 @@
public final class RavenwoodEnvironment {
public static final String TAG = "RavenwoodEnvironment";
- private static final RavenwoodEnvironment sInstance;
- private static final Workaround sWorkaround;
+ private static RavenwoodEnvironment sInstance = new RavenwoodEnvironment();
- private RavenwoodEnvironment() {
- }
-
- static {
- sInstance = new RavenwoodEnvironment();
- sWorkaround = new Workaround();
- ensureRavenwoodInitialized();
- }
-
- public static RuntimeException notSupportedOnDevice() {
+ private static RuntimeException notSupportedOnDevice() {
return new UnsupportedOperationException("This method can only be used on Ravenwood");
}
@@ -52,15 +42,6 @@
}
/**
- * Initialize the ravenwood environment if it hasn't happened already, if running on Ravenwood.
- *
- * No-op if called on the device side.
- */
- @RavenwoodRedirect
- public static void ensureRavenwoodInitialized() {
- }
-
- /**
* USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment.
*
* <p>Using this allows code to behave differently on a real device and on Ravenwood, but
@@ -91,38 +72,10 @@
}
/**
- * See {@link Workaround}. It's only usable on Ravenwood.
- */
- @RavenwoodReplace
- public static Workaround workaround() {
- throw notSupportedOnDevice();
- }
-
- private static Workaround workaround$ravenwood() {
- return sWorkaround;
- }
-
- /**
* @return the "ravenwood-runtime" directory.
*/
@RavenwoodRedirect
public String getRavenwoodRuntimePath() {
throw notSupportedOnDevice();
}
-
- /**
- * A set of APIs used to work around missing features on Ravenwood. Ideally, this class should
- * be empty, and all its APIs should be able to be implemented properly.
- */
- public static class Workaround {
- Workaround() {
- }
-
- /**
- * @return whether the app's target SDK level is at least Q.
- */
- public boolean isTargetSdkAtLeastQ() {
- return true;
- }
- }
}
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 0f16352..9752ff3 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.Bundle;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.Process_ravenwood;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.DeviceConfig_host;
@@ -52,6 +53,7 @@
import com.android.hoststubgen.hosthelper.HostTestUtils;
import com.android.internal.os.RuntimeInit;
import com.android.ravenwood.RavenwoodRuntimeNative;
+import com.android.ravenwood.RavenwoodRuntimeState;
import com.android.ravenwood.common.RavenwoodCommonUtils;
import com.android.ravenwood.common.RavenwoodRuntimeException;
import com.android.ravenwood.common.SneakyThrow;
@@ -223,7 +225,9 @@
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
}
- android.os.Process.init$ravenwood(config.mUid, config.mPid);
+ RavenwoodRuntimeState.sUid = config.mUid;
+ RavenwoodRuntimeState.sPid = config.mPid;
+ RavenwoodRuntimeState.sTargetSdkLevel = config.mTargetSdkLevel;
sOriginalIdentityToken = Binder.clearCallingIdentity();
reinit();
setSystemProperties(config.mSystemProperties);
@@ -350,8 +354,8 @@
if (sOriginalIdentityToken != -1) {
Binder.restoreCallingIdentity(sOriginalIdentityToken);
}
- android.os.Process.reset$ravenwood();
-
+ RavenwoodRuntimeState.reset();
+ Process_ravenwood.reset();
DeviceConfig_host.reset();
try {
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
index 37b0abc..d8f2b70 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.app.Instrumentation;
import android.content.Context;
+import android.os.Build;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -67,7 +68,7 @@
String mTargetPackageName;
int mMinSdkLevel;
- int mTargetSdkLevel;
+ int mTargetSdkLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
boolean mProvideMainThread = false;
diff --git a/ravenwood/runtime-helper-src/framework/android/os/Process_ravenwood.java b/ravenwood/runtime-helper-src/framework/android/os/Process_ravenwood.java
new file mode 100644
index 0000000..3c6a4d7
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/android/os/Process_ravenwood.java
@@ -0,0 +1,70 @@
+/*
+ * 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.os;
+
+import android.util.Pair;
+
+public class Process_ravenwood {
+
+ private static volatile ThreadLocal<Pair<Integer, Boolean>> sThreadPriority;
+
+ static {
+ reset();
+ }
+
+ public static void reset() {
+ // Reset the thread local variable
+ sThreadPriority = ThreadLocal.withInitial(
+ () -> Pair.create(Process.THREAD_PRIORITY_DEFAULT, true));
+ }
+
+ /**
+ * Called by {@link Process#setThreadPriority(int, int)}
+ */
+ public static void setThreadPriority(int tid, int priority) {
+ if (Process.myTid() == tid) {
+ boolean backgroundOk = sThreadPriority.get().second;
+ if (priority >= Process.THREAD_PRIORITY_BACKGROUND && !backgroundOk) {
+ throw new IllegalArgumentException(
+ "Priority " + priority + " blocked by setCanSelfBackground()");
+ }
+ sThreadPriority.set(Pair.create(priority, backgroundOk));
+ } else {
+ throw new UnsupportedOperationException(
+ "Cross-thread priority management not yet available in Ravenwood");
+ }
+ }
+
+ /**
+ * Called by {@link Process#setCanSelfBackground(boolean)}
+ */
+ public static void setCanSelfBackground(boolean backgroundOk) {
+ int priority = sThreadPriority.get().first;
+ sThreadPriority.set(Pair.create(priority, backgroundOk));
+ }
+
+ /**
+ * Called by {@link Process#getThreadPriority(int)}
+ */
+ public static int getThreadPriority(int tid) {
+ if (Process.myTid() == tid) {
+ return sThreadPriority.get().first;
+ } else {
+ throw new UnsupportedOperationException(
+ "Cross-thread priority management not yet available in Ravenwood");
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
index e12ff24..b65668b 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
@@ -23,14 +23,6 @@
}
/**
- * Called from {@link RavenwoodEnvironment#ensureRavenwoodInitialized()}.
- */
- public static void ensureRavenwoodInitialized() {
- // Initialization is now done by RavenwoodAwareTestRunner.
- // Should we remove it?
- }
-
- /**
* Called from {@link RavenwoodEnvironment#getRavenwoodRuntimePath()}.
*/
public static String getRavenwoodRuntimePath(RavenwoodEnvironment env) {
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
index c94ef31..0298171 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
@@ -16,6 +16,7 @@
package android.system;
import com.android.ravenwood.RavenwoodRuntimeNative;
+import com.android.ravenwood.RavenwoodRuntimeState;
import com.android.ravenwood.common.JvmWorkaround;
import java.io.FileDescriptor;
@@ -97,4 +98,16 @@
public static void setenv(String name, String value, boolean overwrite) throws ErrnoException {
RavenwoodRuntimeNative.setenv(name, value, overwrite);
}
+
+ public static int getpid() {
+ return RavenwoodRuntimeState.sPid;
+ }
+
+ public static int getuid() {
+ return RavenwoodRuntimeState.sUid;
+ }
+
+ public static int gettid() {
+ return RavenwoodRuntimeNative.gettid();
+ }
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
index f13189f..7b940b4 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
@@ -58,6 +58,8 @@
public static native void clearSystemProperties();
+ public static native int gettid();
+
public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeState.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeState.java
new file mode 100644
index 0000000..175e020
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeState.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwood;
+
+public class RavenwoodRuntimeState {
+ // This must match VMRuntime.SDK_VERSION_CUR_DEVELOPMENT.
+ public static final int CUR_DEVELOPMENT = 10000;
+
+ public static volatile int sUid;
+ public static volatile int sPid;
+ public static volatile int sTargetSdkLevel;
+
+ static {
+ reset();
+ }
+
+ public static void reset() {
+ sUid = -1;
+ sPid = -1;
+ sTargetSdkLevel = CUR_DEVELOPMENT;
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/VMRuntime.java b/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/VMRuntime.java
index ba89f71..eaadac6 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/VMRuntime.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/VMRuntime.java
@@ -19,6 +19,7 @@
// The original is here:
// $ANDROID_BUILD_TOP/libcore/libart/src/main/java/dalvik/system/VMRuntime.java
+import com.android.ravenwood.RavenwoodRuntimeState;
import com.android.ravenwood.common.JvmWorkaround;
import java.lang.reflect.Array;
@@ -52,4 +53,8 @@
public long addressOf(Object obj) {
return JvmWorkaround.getInstance().addressOf(obj);
}
+
+ public int getTargetSdkVersion() {
+ return RavenwoodRuntimeState.sTargetSdkLevel;
+ }
}
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index 2a3c26e..5b75e98 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <unistd.h>
#include <utils/misc.h>
@@ -173,6 +174,12 @@
throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite ? 1 : 0));
}
+
+static jint Linux_gettid(JNIEnv* env, jobject) {
+ // gettid(2() was added in glibc 2.30 but Android uses an older version in prebuilt.
+ return syscall(__NR_gettid);
+}
+
static void maybeRedirectLog() {
auto ravenwoodLogOut = getenv("RAVENWOOD_LOG_OUT");
if (ravenwoodLogOut == NULL) {
@@ -207,6 +214,7 @@
{ "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat },
{ "nOpen", "(Ljava/lang/String;II)I", (void*)Linux_open },
{ "setenv", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*)Linux_setenv },
+ { "gettid", "()I", (void*)Linux_gettid },
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
diff --git a/ravenwood/tests/runtime-test/Android.bp b/ravenwood/tests/runtime-test/Android.bp
index 4102920..0c0df1f 100644
--- a/ravenwood/tests/runtime-test/Android.bp
+++ b/ravenwood/tests/runtime-test/Android.bp
@@ -10,6 +10,9 @@
android_ravenwood_test {
name: "RavenwoodRuntimeTest",
+ libs: [
+ "ravenwood-helper-runtime",
+ ],
static_libs: [
"androidx.annotation_annotation",
"androidx.test.ext.junit",
diff --git a/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/IdentityTest.java b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/IdentityTest.java
new file mode 100644
index 0000000..8e04b69
--- /dev/null
+++ b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/IdentityTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.runtimetest;
+
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+import static android.os.Process.FIRST_APPLICATION_UID;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Binder;
+import android.os.Build;
+import android.os.Process;
+import android.platform.test.ravenwood.RavenwoodConfig;
+import android.system.Os;
+
+import com.android.ravenwood.RavenwoodRuntimeState;
+
+import dalvik.system.VMRuntime;
+
+import org.junit.Test;
+
+public class IdentityTest {
+
+ @RavenwoodConfig.Config
+ public static final RavenwoodConfig sConfig =
+ new RavenwoodConfig.Builder()
+ .setTargetSdkLevel(UPSIDE_DOWN_CAKE)
+ .setProcessApp()
+ .build();
+
+ @Test
+ public void testUid() {
+ assertEquals(FIRST_APPLICATION_UID, RavenwoodRuntimeState.sUid);
+ assertEquals(FIRST_APPLICATION_UID, Os.getuid());
+ assertEquals(FIRST_APPLICATION_UID, Process.myUid());
+ assertEquals(FIRST_APPLICATION_UID, Binder.getCallingUid());
+ }
+
+ @Test
+ public void testPid() {
+ int pid = RavenwoodRuntimeState.sPid;
+ assertEquals(pid, Os.getpid());
+ assertEquals(pid, Process.myPid());
+ assertEquals(pid, Binder.getCallingPid());
+ }
+
+ @Test
+ public void testTargetSdkLevel() {
+ assertEquals(Build.VERSION_CODES.CUR_DEVELOPMENT, RavenwoodRuntimeState.CUR_DEVELOPMENT);
+ assertEquals(UPSIDE_DOWN_CAKE, RavenwoodRuntimeState.sTargetSdkLevel);
+ assertEquals(UPSIDE_DOWN_CAKE, VMRuntime.getRuntime().getTargetSdkVersion());
+ }
+}
diff --git a/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
index c2230c7..c55506a 100644
--- a/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
+++ b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
@@ -24,6 +24,8 @@
import static android.system.OsConstants.S_ISSOCK;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
@@ -51,10 +53,12 @@
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class OsTest {
+
public interface ConsumerWithThrow<T> {
void accept(T var1) throws Exception;
}
@@ -165,6 +169,35 @@
});
}
+ private static class TestThread extends Thread {
+
+ final CountDownLatch mLatch = new CountDownLatch(1);
+ int mTid;
+
+ TestThread() {
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ mTid = Os.gettid();
+ mLatch.countDown();
+ }
+ }
+
+ @Test
+ public void testGetTid() throws InterruptedException {
+ var t1 = new TestThread();
+ var t2 = new TestThread();
+ t1.start();
+ t2.start();
+ // Wait for thread execution
+ assertTrue(t1.mLatch.await(1, TimeUnit.SECONDS));
+ assertTrue(t2.mLatch.await(1, TimeUnit.SECONDS));
+ // Make sure the tid is unique per-thread
+ assertNotEquals(t1.mTid, t2.mTid);
+ }
+
// Verify StructStat values from libcore against native JVM PosixFileAttributes
private static void assertAttributesEqual(PosixFileAttributes attr, StructStat stat) {
assertEquals(attr.lastModifiedTime(), convertTimespecToFileTime(stat.st_mtim));
diff --git a/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/ProcessTest.java b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/ProcessTest.java
new file mode 100644
index 0000000..d25b5c1
--- /dev/null
+++ b/ravenwood/tests/runtime-test/test/com/android/ravenwoodtest/runtimetest/ProcessTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.runtimetest;
+
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.THREAD_PRIORITY_DEFAULT;
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.os.Process;
+import android.system.Os;
+
+import org.junit.Test;
+
+public class ProcessTest {
+
+ @Test
+ public void testGetUidPidTid() {
+ assertEquals(Os.getuid(), Process.myUid());
+ assertEquals(Os.getpid(), Process.myPid());
+ assertEquals(Os.gettid(), Process.myTid());
+ }
+
+ @Test
+ public void testThreadPriority() {
+ assertThrows(UnsupportedOperationException.class,
+ () -> Process.getThreadPriority(Process.myTid() + 1));
+ assertThrows(UnsupportedOperationException.class,
+ () -> Process.setThreadPriority(Process.myTid() + 1, THREAD_PRIORITY_DEFAULT));
+ assertEquals(THREAD_PRIORITY_DEFAULT, Process.getThreadPriority(Process.myTid()));
+ Process.setThreadPriority(THREAD_PRIORITY_FOREGROUND);
+ assertEquals(THREAD_PRIORITY_FOREGROUND, Process.getThreadPriority(Process.myTid()));
+ Process.setCanSelfBackground(false);
+ Process.setThreadPriority(THREAD_PRIORITY_DEFAULT);
+ assertEquals(THREAD_PRIORITY_DEFAULT, Process.getThreadPriority(Process.myTid()));
+ assertThrows(IllegalArgumentException.class,
+ () -> Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND));
+ }
+}