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

Commit aeac86ed authored by Makoto Onuki's avatar Makoto Onuki
Browse files

[HSG] Allow class directive without policy

In some cases, we want to add a policy for a member (field/method) in
the policy file for a class that already has an annotation.

Previously, we had to always have some policy in the class line, which
could cause confusion because this will essentially override the
annotation, so even when you change the class annotation, that wouldn't
be picked up.

Now update the parser so that a class directive is allowed to omit
a policy.

Also fix b/388562869. But I still need to ignore certain lines in diff
because the merged golden files are already missing the expected lines.

Flag: EXEMPT host test change only
Bug: 292141694
Bug: 388562869
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh -s
Change-Id: Ifa37cd0ff74026bc1ba2c7e8599b159fa0a07412
parent 82e3ee53
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ class android.content.BroadcastReceiver keep
class android.content.Context keep
    method <init> ()V keep
    method getSystemService (Ljava/lang/Class;)Ljava/lang/Object; keep
class android.content.pm.PackageManager keep
class android.content.pm.PackageManager
    method <init> ()V keep
class android.text.ClipboardManager keep
    method <init> ()V keep
+24 −5
Original line number Diff line number Diff line
@@ -89,14 +89,33 @@ filter_output() {
    # - Some other transient lines
    # - Sometimes the javap shows mysterious warnings, so remove them too.
    #
    # `/PATTERN-1/,/PATTERN-2/{//!d}` is a trick to delete lines between two patterns, without
    # the start and the end lines.
    # Most conversion are simple per-line deletion or simple inline replacement with a regex.
    #
    # But removing the constant pool is a bit tricky. It looks like this in the output:
    #---------------------------
    #Constant pool:
    #    #1 = Methodref          #31.#88       // java/lang/Object."<init>":()V
    #    #2 = Class              #89           // java/lang/UnsupportedOperationException
    #    :
    #{ // Or something, I'm not sure if it always ends with a "{".
    #---------------------------
    # i.e. we want to delete all lines from "Constant pool:" as long as the first character
    # is a space.
    #
    # If we simply use '/^Constant pool:/,/^[^ ]/d', then it'll delete the "Constant pool:"
    # line and "{" line too, but again the last line might be important, so we don't want to
    # delete it.
    #
    # So we instead, use '/^Constant pool:/,/^[^ ]/{/^ /d}', which mean:
    # between lines matching '/^Constant pool:/' and '/^[^ ]/', delete lines that start with
    # a space. (=='/^ /d').
    #
    sed -e 's/#[0-9][0-9]*/#x/g' \
        -e 's/^\( *\)[0-9][0-9]*:/\1x:/' \
        -e '/^Constant pool:/,/^[^ ]/{//!d}' \
        -e '/^Constant pool:/,/^[^ ]/{/^ /d}' \
        -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \
        -e '/SHA-256 checksum/d' \
        -e '/Last modified/d' \
        -e '/^ *SHA-256 checksum/d' \
        -e '/^ *Last modified/d' \
        -e '/^Classfile jar/d' \
        -e '/\[warning\]/d'
  else
+21 −7
Original line number Diff line number Diff line
@@ -413,8 +413,8 @@ class TextFileFilterPolicyParser {
    }

    private fun parseClass(fields: Array<String>) {
        if (fields.size < 3) {
            throw ParseException("Class ('c') expects 2 fields.")
        if (fields.size <= 1) {
            throw ParseException("Class ('c') expects 1 or 2 fields.")
        }
        val className = fields[1]

@@ -424,7 +424,9 @@ class TextFileFilterPolicyParser {
        // :aidl, etc?
        val classType = resolveSpecialClass(className)

        if (fields[2].startsWith("!")) {
        val policyStr = if (fields.size > 2) { fields[2] } else { "" }

        if (policyStr.startsWith("!")) {
            if (classType != SpecialClass.NotSpecial) {
                // We could support it, but not needed at least for now.
                throw ParseException(
@@ -432,10 +434,10 @@ class TextFileFilterPolicyParser {
                )
            }
            // It's a redirection class.
            val toClass = fields[2].substring(1)
            val toClass = policyStr.substring(1)

            processor.onRedirectionClass(className, toClass)
        } else if (fields[2].startsWith("~")) {
        } else if (policyStr.startsWith("~")) {
            if (classType != SpecialClass.NotSpecial) {
                // We could support it, but not needed at least for now.
                throw ParseException(
@@ -443,11 +445,23 @@ class TextFileFilterPolicyParser {
                )
            }
            // It's a class-load hook
            val callback = fields[2].substring(1)
            val callback = policyStr.substring(1)

            processor.onClassLoadHook(className, callback)
        } else {
            val policy = parsePolicy(fields[2])
            // Special case: if it's a class directive with no policy, then it encloses
            // members, but we don't apply any policy to the class itself.
            // This is only allowed in a not-special case.
            if (policyStr == "") {
                if (classType == SpecialClass.NotSpecial && superClass == null) {
                    currentClassName = className
                    processor.onSimpleClassStart(className)
                    return
                }
                throw ParseException("Special class or subclass directive must have a policy")
            }

            val policy = parsePolicy(policyStr)
            if (!policy.isUsableWithClasses) {
                throw ParseException("Class can't have policy '$policy'")
            }
+3 −6
Original line number Diff line number Diff line
@@ -37,8 +37,7 @@ SCRIPT_NAME="${0##*/}"
GOLDEN_DIR=${GOLDEN_DIR:-golden-output}
mkdir -p $GOLDEN_DIR

# TODO(b/388562869) We shouldn't need `--ignore-matching-lines`, but the golden files may not have the "Constant pool:" lines.
DIFF_CMD=${DIFF_CMD:-diff -u --ignore-blank-lines --ignore-space-change --ignore-matching-lines='^\(Constant.pool:\|{\)$'}
DIFF_CMD=${DIFF_CMD:-./tiny-framework-dump-test.py run-diff}

update=0
three_way=0
@@ -63,12 +62,10 @@ done
shift $(($OPTIND - 1))

# Build the dump files, which are the input of this test.
run ${BUILD_CMD:=m} dump-jar tiny-framework-dump-test

run ${BUILD_CMD:-m} dump-jar tiny-framework-dump-test

# Get the path to the generate text files. (not the golden files.)
# We get them from $OUT/module-info.json

files=(
$(python3 -c '
import sys
+18 −2
Original line number Diff line number Diff line
@@ -28,9 +28,16 @@ GOLDEN_DIRS = [

# Run diff.
def run_diff(file1, file2):
    # TODO(b/388562869) We shouldn't need `--ignore-matching-lines`, but the golden files may not have the "Constant pool:" lines.
    command = ['diff', '-u', '--ignore-blank-lines',
    command = ['diff', '-u',
               '--ignore-blank-lines',
               '--ignore-space-change',

               # Ignore the class file version.
               '--ignore-matching-lines=^ *\(major\|minor\) version:$',

               # We shouldn't need `--ignore-matching-lines`, but somehow
               # the golden files were generated without these lines for b/388562869,
               # so let's just ignore them.
               '--ignore-matching-lines=^\(Constant.pool:\|{\)$',
               file1, file2]
    print(' '.join(command))
@@ -85,4 +92,13 @@ class TestWithGoldenOutput(unittest.TestCase):


if __name__ == "__main__":
    args = sys.argv

    # This script is used by diff-and-update-golden.sh too.
    if len(args) > 1 and args[1] == "run-diff":
        if run_diff(args[2], args[3]):
            sys.exit(0)
        else:
            sys.exit(1)

    unittest.main(verbosity=2)