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

Commit bdf982da authored by John Wu's avatar John Wu
Browse files

[HostStubGen] Fix class-wide policy filter

- It didn't handle class names with '$' properly
- It uses unnecessary loops, as recursion already handles it

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: I8e2cfebfd115a9e450dce3e4aecd6b53e0ad46f2
parent f584cfc3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -213,9 +213,9 @@ com.unsupported.*
"

run_hoststubgen_for_failure "One specific class disallowed" \
    "TinyFrameworkClassAnnotations is not allowed to have Ravenwood annotations" \
    "TinyFrameworkAnnotations is not allowed to have Ravenwood annotations" \
    "
!com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
!com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations
* # All other classes allowed
"

+0 −12
Original line number Diff line number Diff line
@@ -201,18 +201,6 @@ fun isAnonymousInnerClass(cn: ClassNode): Boolean {
    return cn.name.matches(numericalInnerClassName)
}

/**
 * Take a class name. If it's a nested class, then return the name of its direct outer class name.
 * Otherwise, return null.
 */
fun getDirectOuterClassName(className: String): String? {
    val pos = className.lastIndexOf('$')
    if (pos < 0) {
        return null
    }
    return className.substring(0, pos)
}

/**
 * Write bytecode to push all the method arguments to the stack.
 * The number of arguments and their type are taken from [methodDescriptor].
+45 −49
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.hoststubgen.filters

import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.getDirectOuterClassName

/**
 * This is used as the second last fallback filter. This filter propagates the class-wide policy
@@ -24,22 +23,34 @@ import com.android.hoststubgen.asm.getDirectOuterClassName
 */
class ClassWidePolicyPropagatingFilter(
    private val classes: ClassNodes,
    fallback: OutputFilter,
    fallback: OutputFilter
) : DelegatingFilter(fallback) {

    private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
    /**
     * We don't use ClassNode.outerClass, because it gives as the top-level
     * outer class (A$B$C -> A), not the direct outer class (A$B$C -> A$B).
     *
     * Sometimes a class name includes `$`, but is not as a nested class name separator
     * (e.g. a class name like `MyClass$$`). In this case, `MyClass$` is not actually a class.
     *
     * So before getting the class policy on a nonexistent class, which may cause an
     * incorrect result, we make sure the class actually exists.
     */
    private fun getDirectOuterClass(className: String): String? {
        var currentClass = className


        // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy
        // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A.
        while (true) {
            // Sometimes a class name has a `$` in it but not as a nest class name separator --
            // e.g. class name like "MyClass$$". In this case, `MyClass$` may not actually be
            // a class name.
            // So before getting the class policy on a nonexistent class, which may cause an
            // incorrect result, we make sure if className actually exists.
            if (classes.hasClass(className)) {
            val pos = currentClass.lastIndexOf('$')
            if (pos < 0) {
                return null
            }
            currentClass = currentClass.substring(0, pos)
            if (classes.hasClass(currentClass)) {
                return currentClass
            }
        }
    }

    private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
        outermostFilter.getPolicyForClass(className).let { policy ->
            if (policy.policy.isClassWidePolicy) {
                val p = if (resolve) {
@@ -49,39 +60,24 @@ class ClassWidePolicyPropagatingFilter(
                }

                return p.withReason(policy.reason)
                            .wrapReason("class-wide in $currentClass")
                    .wrapReason("class-wide in $className")
            }
            // If the class's policy is remove, then remove it.
            if (policy.policy == FilterPolicy.Remove) {
                        return FilterPolicy.Remove.withReason("class-wide in $currentClass")
                    }
                return FilterPolicy.Remove.withReason("class-wide in $className")
            }
        }

            // Next, look at the outer class...
            val outer = getDirectOuterClassName(currentClass)
            if (outer == null) {
        return null
    }
            currentClass = outer
        }
    }

    override fun getPolicyForClass(className: String): FilterPolicyWithReason {
        // If it's a nested class, use the outer class's policy.
        getDirectOuterClassName(className)?.let { outerName ->
            getClassWidePolicy(outerName, resolve = false)?.let { policy ->
                return policy
            }
        }

        return super.getPolicyForClass(className)
        // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy
        // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A, recursively
        return getDirectOuterClass(className)?.let { getClassWidePolicy(it, resolve = false) }
            ?: super.getPolicyForClass(className)
    }

    override fun getPolicyForField(
            className: String,
            fieldName: String
    ): FilterPolicyWithReason {
    override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
        return getClassWidePolicy(className, resolve = true)
                ?: super.getPolicyForField(className, fieldName)
    }
+2 −2
Original line number Diff line number Diff line
@@ -6,10 +6,10 @@


# To allow a specific class to use annotations:
# com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
# com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations

# To disallow a specific class to use annotations:
# !com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
# !com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations

# To allow a specific package to use annotations:
# com.android.hoststubgen.test.*
+224 −258

File changed.

Preview size limit exceeded, changes collapsed.

Loading