Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98c92c15 authored by John Wu's avatar John Wu
Browse files

[HostStubGen] Allow method policy to override native substitution

A policy explicitly set on the method should override the class-level
native substitution setting. In order to do so, we introduce a new
method-level "NativeSubstitution" policy that can only be propagated
from a class-wide level, which makes it possible to override it in outer
filter levels (e.g. text policy + annotation policy).

We also update BodyReplacingMethodVisitor to support writing code into
methods without a body, so that all body replacing policies can be used
on any method.

Bug: 292141694
Flag: EXEMPT host test change only
Test: atest hoststubgen-test-tiny-test
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Change-Id: I75c016b96bf52e97dc0e685419abad23650e958b
parent ed2255ab
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -60,7 +60,9 @@ public final class RavenwoodEnvironment {
    public static void ensureRavenwoodInitialized() {
    }

    private static native void ensureRavenwoodInitialized$ravenwood();
    private static void ensureRavenwoodInitialized$ravenwood() {
        nativeEnsureRavenwoodInitialized();
    }

    /**
     * USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment.
@@ -92,7 +94,9 @@ public final class RavenwoodEnvironment {
        throw notSupportedOnDevice();
    }

    private native <T> T fromAddress$ravenwood(long address);
    private <T> T fromAddress$ravenwood(long address) {
        return nativeFromAddress(address);
    }

    /**
     * See {@link Workaround}. It's only usable on Ravenwood.
@@ -114,7 +118,14 @@ public final class RavenwoodEnvironment {
        throw notSupportedOnDevice();
    }

    private native String getRavenwoodRuntimePath$ravenwood();
    private String getRavenwoodRuntimePath$ravenwood() {
        return nativeGetRavenwoodRuntimePath();
    }

    // Private native methods that are actually substituted on Ravenwood
    private native <T> T nativeFromAddress(long address);
    private native String nativeGetRavenwoodRuntimePath();
    private static native void nativeEnsureRavenwoodInitialized();

    /**
     * A set of APIs used to work around missing features on Ravenwood. Ideally, this class should
+3 −3
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public class RavenwoodEnvironment_host {
    /**
     * Called from {@link RavenwoodEnvironment#ensureRavenwoodInitialized()}.
     */
    public static void ensureRavenwoodInitialized() {
    public static void nativeEnsureRavenwoodInitialized() {

        // TODO Unify it with the initialization code in RavenwoodAwareTestRunnerHook.

@@ -63,14 +63,14 @@ public class RavenwoodEnvironment_host {
    /**
     * Called from {@link RavenwoodEnvironment#getRavenwoodRuntimePath()}.
     */
    public static String getRavenwoodRuntimePath(RavenwoodEnvironment env) {
    public static String nativeGetRavenwoodRuntimePath(RavenwoodEnvironment env) {
        return RavenwoodCommonUtils.getRavenwoodRuntimePath();
    }

    /**
     * Called from {@link RavenwoodEnvironment#fromAddress(long)}.
     */
    public static <T> T fromAddress(RavenwoodEnvironment env, long address) {
    public static <T> T nativeFromAddress(RavenwoodEnvironment env, long address) {
        return JvmWorkaround.getInstance().fromAddress(address);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.hoststubgen.filters.DefaultHookInjectingFilter
import com.android.hoststubgen.filters.FilterPolicy
import com.android.hoststubgen.filters.FilterRemapper
import com.android.hoststubgen.filters.ImplicitOutputFilter
import com.android.hoststubgen.filters.NativeFilter
import com.android.hoststubgen.filters.OutputFilter
import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
import com.android.hoststubgen.filters.printAsTextPolicy
@@ -132,6 +133,9 @@ class HostStubGen(val options: HostStubGenOptions) {
        // The first filter is for the default policy from the command line options.
        var filter: OutputFilter = ConstantFilter(options.defaultPolicy.get, "default-by-options")

        // Next, we build a filter that preserves all native methods by default
        filter = NativeFilter(allClasses, filter)

        // Next, we need a filter that resolves "class-wide" policies.
        // This is used when a member (methods, fields, nested classes) don't get any polices
        // from upper filters. e.g. when a method has no annotations, then this filter will apply
+4 −0
Original line number Diff line number Diff line
@@ -327,6 +327,10 @@ fun MethodNode.isPublic(): Boolean {
    return (this.access and Opcodes.ACC_PUBLIC) != 0
}

fun MethodNode.isNative(): Boolean {
    return (this.access and Opcodes.ACC_NATIVE) != 0
}

fun MethodNode.isSpecial(): Boolean {
    return CTOR_NAME == this.name || CLASS_INITIALIZER_NAME == this.name
}
+12 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.hoststubgen.filters

import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.isNative

/**
 * This is used as the second last fallback filter. This filter propagates the class-wide policy
@@ -87,7 +88,16 @@ class ClassWidePolicyPropagatingFilter(
        methodName: String,
        descriptor: String
    ): FilterPolicyWithReason {
        return getClassWidePolicy(className, resolve = true)
        return outermostFilter.getNativeSubstitutionClass(className)?.let {
            // First check native substitution
            classes.findMethod(className, methodName, descriptor)?.let { mn ->
                if (mn.isNative()) {
                    FilterPolicy.NativeSubstitute.withReason("class-wide in $className")
                } else {
                    null
                }
            }
        } ?: getClassWidePolicy(className, resolve = true)
        ?: super.getPolicyForMethod(className, methodName, descriptor)
    }
}
 No newline at end of file
Loading