summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/Binder.java96
-rw-r--r--core/java/android/os/IBinder.java1
-rw-r--r--core/java/android/os/Process.java32
-rw-r--r--core/java/android/os/SystemClock.java39
-rw-r--r--ravenwood/Android.bp3
-rw-r--r--ravenwood/framework-minus-apex-ravenwood-policies.txt18
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java71
-rw-r--r--ravenwood/ravenwood-annotation-allowed-classes.txt6
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java2
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt8
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)