diff options
10 files changed, 262 insertions, 14 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 995622004fa6..0ccc485a34f4 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -30,9 +30,11 @@ import com.android.internal.os.BinderCallHeavyHitterWatcher; import com.android.internal.os.BinderCallHeavyHitterWatcher.BinderCallHeavyHitterListener; import com.android.internal.os.BinderInternal; import com.android.internal.os.BinderInternal.CallSession; +import com.android.internal.os.SomeArgs; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.FunctionalUtils.ThrowingSupplier; +import com.android.internal.util.Preconditions; import dalvik.annotation.optimization.CriticalNative; @@ -46,6 +48,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Modifier; import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.function.Supplier; /** * Base class for a remotable object, the core part of a lightweight @@ -289,6 +292,33 @@ public class Binder implements IBinder { sWarnOnBlockingOnCurrentThread.set(sWarnOnBlocking); } + private static ThreadLocal<SomeArgs> sIdentity$ravenwood; + + @android.ravenwood.annotation.RavenwoodKeepWholeClass + private static class IdentitySupplier implements Supplier<SomeArgs> { + @Override + public SomeArgs get() { + final SomeArgs args = SomeArgs.obtain(); + // Match IPCThreadState behavior + args.arg1 = Boolean.FALSE; + args.argi1 = android.os.Process.myUid(); + args.argi2 = android.os.Process.myPid(); + return args; + } + } + + /** @hide */ + @android.ravenwood.annotation.RavenwoodKeep + public static void init$ravenwood() { + sIdentity$ravenwood = ThreadLocal.withInitial(new IdentitySupplier()); + } + + /** @hide */ + @android.ravenwood.annotation.RavenwoodKeep + public static void reset$ravenwood() { + sIdentity$ravenwood = null; + } + /** * Raw native pointer to JavaBBinderHolder object. Owned by this Java object. Not null. */ @@ -312,8 +342,14 @@ public class Binder implements IBinder { * Warning: oneway transactions do not receive PID. */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static final native int getCallingPid(); + /** @hide */ + public static final int getCallingPid$ravenwood() { + return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().argi2; + } + /** * Return the Linux UID assigned to the process that sent you the * current transaction that is being processed. This UID can be used with @@ -322,8 +358,14 @@ public class Binder implements IBinder { * incoming transaction, then its own UID is returned. */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static final native int getCallingUid(); + /** @hide */ + public static final int getCallingUid$ravenwood() { + return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().argi1; + } + /** * Returns {@code true} if the current thread is currently executing an * incoming transaction. @@ -331,6 +373,7 @@ public class Binder implements IBinder { * @hide */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static final native boolean isDirectlyHandlingTransactionNative(); /** @hide */ @@ -344,6 +387,7 @@ public class Binder implements IBinder { /** * @hide */ + @android.ravenwood.annotation.RavenwoodKeep public static final boolean isDirectlyHandlingTransaction() { return sIsHandlingBinderTransaction || isDirectlyHandlingTransactionNative(); } @@ -363,8 +407,15 @@ public class Binder implements IBinder { * @hide */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace private static native boolean hasExplicitIdentity(); + /** @hide */ + private static boolean hasExplicitIdentity$ravenwood() { + return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).get().arg1 + == Boolean.TRUE; + } + /** * Return the Linux UID assigned to the process that sent the transaction * currently being processed. @@ -373,6 +424,7 @@ public class Binder implements IBinder { * executing an incoming transaction and the calling identity has not been * explicitly set with {@link #clearCallingIdentity()} */ + @android.ravenwood.annotation.RavenwoodKeep public static final int getCallingUidOrThrow() { if (!isDirectlyHandlingTransaction() && !hasExplicitIdentity()) { throw new IllegalStateException( @@ -434,8 +486,26 @@ public class Binder implements IBinder { * @see #restoreCallingIdentity(long) */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static final native long clearCallingIdentity(); + /** @hide */ + public static final long clearCallingIdentity$ravenwood() { + final SomeArgs args = Preconditions.requireNonNullViaRavenwoodRule( + sIdentity$ravenwood).get(); + long res = ((long) args.argi1 << 32) | args.argi2; + if (args.arg1 == Boolean.TRUE) { + res |= (0x1 << 30); + } else { + res &= ~(0x1 << 30); + } + // Match IPCThreadState behavior + args.arg1 = Boolean.TRUE; + args.argi1 = android.os.Process.myUid(); + args.argi2 = android.os.Process.myPid(); + return res; + } + /** * Restore the identity of the incoming IPC on the current thread * back to a previously identity that was returned by {@link @@ -447,8 +517,18 @@ public class Binder implements IBinder { * @see #clearCallingIdentity */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static final native void restoreCallingIdentity(long token); + /** @hide */ + public static final void restoreCallingIdentity$ravenwood(long token) { + final SomeArgs args = Preconditions.requireNonNullViaRavenwoodRule( + sIdentity$ravenwood).get(); + args.arg1 = ((token & (0x1 << 30)) != 0) ? Boolean.TRUE : Boolean.FALSE; + args.argi1 = (int) (token >> 32); + args.argi2 = (int) (token & ~(0x1 << 30)); + } + /** * Convenience method for running the provided action enclosed in * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}. @@ -644,8 +724,14 @@ public class Binder implements IBinder { * in order to prevent the process from holding on to objects longer than * it needs to. */ + @android.ravenwood.annotation.RavenwoodReplace public static final native void flushPendingCommands(); + /** @hide */ + public static final void flushPendingCommands$ravenwood() { + // Ravenwood doesn't support IPC; ignored + } + /** * Add the calling thread to the IPC thread pool. This function does * not return until the current process is exiting. @@ -703,6 +789,7 @@ public class Binder implements IBinder { * <p>If you're creating a Binder token (a Binder object without an attached interface), * you should use {@link #Binder(String)} instead. */ + @android.ravenwood.annotation.RavenwoodKeep public Binder() { this(null); } @@ -719,6 +806,7 @@ public class Binder implements IBinder { * Instead of creating multiple tokens with the same descriptor, consider adding a suffix to * help identify them. */ + @android.ravenwood.annotation.RavenwoodKeep public Binder(@Nullable String descriptor) { mObject = getNativeBBinderHolder(); if (mObject != 0L) { @@ -742,6 +830,7 @@ public class Binder implements IBinder { * will be implemented for you to return the given owner IInterface when * the corresponding descriptor is requested. */ + @android.ravenwood.annotation.RavenwoodKeep public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) { mOwner = owner; mDescriptor = descriptor; @@ -750,6 +839,7 @@ public class Binder implements IBinder { /** * Default implementation returns an empty interface name. */ + @android.ravenwood.annotation.RavenwoodKeep public @Nullable String getInterfaceDescriptor() { return mDescriptor; } @@ -758,6 +848,7 @@ public class Binder implements IBinder { * Default implementation always returns true -- if you got here, * the object is alive. */ + @android.ravenwood.annotation.RavenwoodKeep public boolean pingBinder() { return true; } @@ -768,6 +859,7 @@ public class Binder implements IBinder { * Note that if you're calling on a local binder, this always returns true * because your process is alive if you're calling it. */ + @android.ravenwood.annotation.RavenwoodKeep public boolean isBinderAlive() { return true; } @@ -777,6 +869,7 @@ public class Binder implements IBinder { * to return the associated {@link IInterface} if it matches the requested * descriptor. */ + @android.ravenwood.annotation.RavenwoodKeep public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) { if (mDescriptor != null && mDescriptor.equals(descriptor)) { return mOwner; @@ -1250,12 +1343,14 @@ public class Binder implements IBinder { /** * Local implementation is a no-op. */ + @android.ravenwood.annotation.RavenwoodKeep public void linkToDeath(@NonNull DeathRecipient recipient, int flags) { } /** * Local implementation is a no-op. */ + @android.ravenwood.annotation.RavenwoodKeep public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags) { return true; } @@ -1283,6 +1378,7 @@ public class Binder implements IBinder { } } + @android.ravenwood.annotation.RavenwoodReplace private static native long getNativeBBinderHolder(); private static long getNativeBBinderHolder$ravenwood() { diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 90e4b17250d8..91c2965c2505 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -194,6 +194,7 @@ public interface IBinder { * Limit that should be placed on IPC sizes, in bytes, to keep them safely under the transaction * buffer limit. */ + @android.ravenwood.annotation.RavenwoodKeep static int getSuggestedMaxIpcSizeBytes() { return MAX_IPC_SIZE; } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 677143afd4fb..daec1721977b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -34,6 +34,9 @@ import android.system.StructPollfd; import android.util.Pair; import android.webkit.WebViewZygote; +import com.android.internal.os.SomeArgs; +import com.android.internal.util.Preconditions; + import dalvik.system.VMRuntime; import libcore.io.IoUtils; @@ -833,14 +836,37 @@ public class Process { return VMRuntime.getRuntime().is64Bit(); } + private static SomeArgs sIdentity$ravenwood; + + /** @hide */ + @android.ravenwood.annotation.RavenwoodKeep + public static void init$ravenwood(int uid, int pid) { + final SomeArgs args = SomeArgs.obtain(); + args.argi1 = uid; + args.argi2 = pid; + sIdentity$ravenwood = 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 public static final int myPid() { return Os.getpid(); } + /** @hide */ + public static final int myPid$ravenwood() { + return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).argi2; + } + /** * Returns the identifier of this process' parent. * @hide @@ -864,10 +890,16 @@ public class Process { * 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 public static final int myUid() { return Os.getuid(); } + /** @hide */ + public static final int myUid$ravenwood() { + return Preconditions.requireNonNullViaRavenwoodRule(sIdentity$ravenwood).argi1; + } + /** * Returns this process's user handle. This is the * user the process is running under. It is distinct from diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 831ca86504af..49a0bd3289aa 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -24,6 +24,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.location.ILocationManager; import android.location.LocationTime; +import android.text.format.DateUtils; import android.util.Slog; import dalvik.annotation.optimization.CriticalNative; @@ -125,6 +126,7 @@ public final class SystemClock { * * @param ms to sleep before returning, in milliseconds of uptime. */ + @android.ravenwood.annotation.RavenwoodKeep public static void sleep(long ms) { long start = uptimeMillis(); @@ -186,8 +188,16 @@ public final class SystemClock { * @return milliseconds of non-sleep uptime since boot. */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace native public static long uptimeMillis(); + /** @hide */ + public static long uptimeMillis$ravenwood() { + // Ravenwood booted in Jan 2023, and has been in deep sleep for one week + return System.currentTimeMillis() - (1672556400L * 1_000) + - (DateUtils.WEEK_IN_MILLIS * 1_000); + } + /** * Returns nanoseconds since boot, not counting time spent in deep sleep. * @@ -195,8 +205,16 @@ public final class SystemClock { * @hide */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static native long uptimeNanos(); + /** @hide */ + public static long uptimeNanos$ravenwood() { + // Ravenwood booted in Jan 2023, and has been in deep sleep for one week + return System.nanoTime() - (1672556400L * 1_000_000_000) + - (DateUtils.WEEK_IN_MILLIS * 1_000_000_000); + } + /** * Return {@link Clock} that starts at system boot, not counting time spent * in deep sleep. @@ -218,8 +236,15 @@ public final class SystemClock { * @return elapsed milliseconds since boot. */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace native public static long elapsedRealtime(); + /** @hide */ + public static long elapsedRealtime$ravenwood() { + // Ravenwood booted in Jan 2023, and has been in deep sleep for one week + return System.currentTimeMillis() - (1672556400L * 1_000); + } + /** * Return {@link Clock} that starts at system boot, including time spent in * sleep. @@ -241,8 +266,15 @@ public final class SystemClock { * @return elapsed nanoseconds since boot. */ @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static native long elapsedRealtimeNanos(); + /** @hide */ + public static long elapsedRealtimeNanos$ravenwood() { + // Ravenwood booted in Jan 2023, and has been in deep sleep for one week + return System.nanoTime() - (1672556400L * 1_000_000_000); + } + /** * Returns milliseconds running in the current thread. * @@ -271,8 +303,15 @@ public final class SystemClock { */ @UnsupportedAppUsage @CriticalNative + @android.ravenwood.annotation.RavenwoodReplace public static native long currentTimeMicro(); + /** @hide */ + public static long currentTimeMicro$ravenwood() { + // Ravenwood booted in Jan 2023, and has been in deep sleep for one week + return System.nanoTime() / 1000L; + } + /** * Returns milliseconds since January 1, 1970 00:00:00.0 UTC, synchronized * using a remote network source outside the device. diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index ec12d2171a93..fc4ed1d4d527 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -28,9 +28,8 @@ java_library { name: "ravenwood-junit", srcs: ["junit-src/**/*.java"], libs: [ + "framework-minus-apex.ravenwood", "junit", ], - sdk_version: "core_current", - host_supported: true, visibility: ["//visibility:public"], } diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/framework-minus-apex-ravenwood-policies.txt index 48d5722fed8e..692d598ac2bb 100644 --- a/ravenwood/framework-minus-apex-ravenwood-policies.txt +++ b/ravenwood/framework-minus-apex-ravenwood-policies.txt @@ -81,6 +81,8 @@ class com.android.internal.util.LineBreakBufferedWriter stubclass class com.android.internal.util.Preconditions stubclass class com.android.internal.util.StringPool stubclass +class com.android.internal.os.SomeArgs stubclass + # Parcel class android.os.Parcel stubclass method writeException (Ljava/lang/Exception;)V @writeException$ravenwood @@ -92,14 +94,16 @@ class android.os.ParcelFormatException stubclass class android.os.BadParcelableException stubclass class android.os.BadTypeParcelableException stubclass -# Binder: just enough to construct, no further functionality -class android.os.Binder stub - method <init> ()V stub - method <init> (Ljava/lang/String;)V stub - method isDirectlyHandlingTransaction ()Z stub - method isDirectlyHandlingTransactionNative ()Z @isDirectlyHandlingTransactionNative$ravenwood - method getNativeBBinderHolder ()J @getNativeBBinderHolder$ravenwood +# Binder +class android.os.DeadObjectException stubclass +class android.os.DeadSystemException stubclass +class android.os.RemoteException stubclass +class android.os.TransactionTooLargeException stubclass # Containers class android.os.BaseBundle stubclass class android.os.Bundle stubclass + +# Misc +class android.os.PatternMatcher stubclass +class android.os.ParcelUuid stubclass diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java index a6b3f668efa6..bffd0cdc9412 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java @@ -16,6 +16,7 @@ package android.platform.test.ravenwood; +import android.os.Process; import android.platform.test.annotations.IgnoreUnderRavenwood; import org.junit.Assume; @@ -23,6 +24,8 @@ import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; +import java.util.concurrent.atomic.AtomicInteger; + /** * THIS RULE IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY * QUESTIONS ABOUT IT. @@ -30,20 +33,84 @@ import org.junit.runners.model.Statement; * @hide */ public class RavenwoodRule implements TestRule { + private static AtomicInteger sNextPid = new AtomicInteger(100); + + /** + * Unless the test author requests differently, run as "nobody", and give each collection of + * tests its own unique PID. + */ + private int mUid = android.os.Process.NOBODY_UID; + private int mPid = sNextPid.getAndIncrement(); + + public RavenwoodRule() { + } + + public static class Builder { + private RavenwoodRule mRule = new RavenwoodRule(); + + public Builder() { + } + + /** + * Configure the identity of this process to be the system UID for the duration of the + * test. Has no effect under non-Ravenwood environments. + */ + public Builder setProcessSystem() { + mRule.mUid = android.os.Process.SYSTEM_UID; + return this; + } + + /** + * Configure the identity of this process to be an app UID for the duration of the + * test. Has no effect under non-Ravenwood environments. + */ + public Builder setProcessApp() { + mRule.mUid = android.os.Process.FIRST_APPLICATION_UID; + return this; + } + + public RavenwoodRule build() { + return mRule; + } + } + + /** + * Return if the current process is running under a Ravenwood test environment. + */ public boolean isUnderRavenwood() { // TODO: give ourselves a better environment signal return System.getProperty("java.class.path").contains("ravenwood"); } + private void init() { + android.os.Process.init$ravenwood(mUid, mPid); + android.os.Binder.init$ravenwood(); + } + + private void reset() { + android.os.Process.reset$ravenwood(); + android.os.Binder.reset$ravenwood(); + } + @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { + final boolean isUnderRavenwood = isUnderRavenwood(); if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) { - Assume.assumeFalse(isUnderRavenwood()); + Assume.assumeFalse(isUnderRavenwood); + } + if (isUnderRavenwood) { + init(); + } + try { + base.evaluate(); + } finally { + if (isUnderRavenwood) { + reset(); + } } - base.evaluate(); } }; } diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/ravenwood-annotation-allowed-classes.txt index c6dd6e39607e..776a19a68a31 100644 --- a/ravenwood/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/ravenwood-annotation-allowed-classes.txt @@ -1,3 +1,9 @@ # Only classes listed here can use the Ravenwood annotations. com.android.internal.util.ArrayUtils + +android.os.Binder +android.os.Binder$IdentitySupplier +android.os.IBinder +android.os.Process +android.os.SystemClock diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java index 25abbace85de..c770b9ccc800 100644 --- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java +++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java @@ -65,7 +65,7 @@ public class HostTestUtils { */ public static void onThrowMethodCalled() { // TODO: Maybe add call tracking? - throw new AssumptionViolatedException("This method is not supported on the host side"); + throw new RuntimeException("This method is not supported on the host side"); } /** diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt index ee67f0f9a72b..5a7d78aec0a6 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt @@ -387,13 +387,17 @@ class AnnotationBasedFilter( } // This mn has "SubstituteWith". This means, - // 1. Re move the "rename-to" method, so add it to substitutedMethods. + // 1. Re move the "rename-to" method, so add it to substitutedMethods. policiesFromSubstitution[MethodKey(renameTo, mn.desc)] = FilterPolicy.Remove.withReason("substitute-to") + // If the policy is "stub", use "stub". + // Otherwise, it must be "keep" or "throw", but there's no point in using + // "throw", so let's use "keep". + val newPolicy = if (policy.needsInStub) policy else FilterPolicy.Keep // 2. We also keep the from-to in the map. policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] = - policy.withReason("substitute-from") + newPolicy.withReason("substitute-from") substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo) |