Loading Ravenwood.bp +2 −1 Original line number Diff line number Diff line Loading @@ -159,7 +159,8 @@ java_library { "framework-minus-apex.ravenwood", ], sdk_version: "core_platform", jarjar_rules: ":ravenwood-framework-jarjar-rules", // See b/313930116. Jarjar is too slow on this jar. We use HostStubGen to do the rename. // jarjar_rules: ":ravenwood-framework-jarjar-rules", } java_genrule { Loading ravenwood/texts/ravenwood-framework-jarjar-rules.txt +1 −2 Original line number Diff line number Diff line # To avoid VerifyError on nano proto files (b/324063814) rule com.**.nano.** devicenano.@0 # Applying jarjar on framework-minux-apex is too slow, so we don't use jarjar for now. b/313930116 No newline at end of file ravenwood/texts/ravenwood-framework-policies.txt +5 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,11 @@ class :feature_flags keepclass # Keep all sysprops generated code implementations class :sysprops keepclass # To avoid VerifyError on nano proto files (b/324063814), we rename nano proto classes. # Note: The "rename" directive must use shashes (/) as a package name separator. rename com/.*/nano/ devicenano/ rename android/.*/nano/ devicenano/ # Exported to Mainline modules; cannot use annotations class com.android.internal.util.FastXmlSerializer keepclass class com.android.internal.util.FileRotator keepclass Loading tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +39 −14 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import com.android.hoststubgen.visitors.PackageRedirectRemapper import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassVisitor import org.objectweb.asm.ClassWriter import org.objectweb.asm.commons.ClassRemapper import org.objectweb.asm.commons.Remapper import org.objectweb.asm.util.CheckClassAdapter import java.io.BufferedInputStream import java.io.FileOutputStream Loading Loading @@ -70,7 +72,7 @@ class HostStubGen(val options: HostStubGenOptions) { } // Build the filters. val filter = buildFilter(errors, allClasses, options) val (filter, policyFileRemapper) = buildFilter(errors, allClasses, options) // Transform the jar. convert( Loading @@ -82,6 +84,7 @@ class HostStubGen(val options: HostStubGenOptions) { allClasses, errors, stats, policyFileRemapper, ) // Dump statistics, if specified. Loading @@ -107,7 +110,7 @@ class HostStubGen(val options: HostStubGenOptions) { errors: HostStubGenErrors, allClasses: ClassNodes, options: HostStubGenOptions, ): OutputFilter { ): Pair<OutputFilter, Remapper?> { // We build a "chain" of multiple filters here. // // The filters are build in from "inside", meaning the first filter created here is Loading Loading @@ -160,10 +163,14 @@ class HostStubGen(val options: HostStubGenOptions) { filter, ) var policyFileRemapper: Remapper? = null // Next, "text based" filter, which allows to override polices without touching // the target code. options.policyOverrideFile.ifSet { filter = createFilterFromTextPolicyFile(it, allClasses, filter) val (f, p) = createFilterFromTextPolicyFile(it, allClasses, filter) filter = f policyFileRemapper = p } // If `--intersect-stub-jar` is provided, load from these jar files too. Loading @@ -178,7 +185,7 @@ class HostStubGen(val options: HostStubGenOptions) { // Apply the implicit filter. filter = ImplicitOutputFilter(errors, allClasses, filter) return filter return Pair(filter, policyFileRemapper) } /** Loading @@ -205,6 +212,7 @@ class HostStubGen(val options: HostStubGenOptions) { classes: ClassNodes, errors: HostStubGenErrors, stats: HostStubGenStats, remapper: Remapper?, ) { log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar) log.i("ASM CheckClassAdapter is %s", if (enableChecker) "enabled" else "disabled") Loading @@ -222,8 +230,8 @@ class HostStubGen(val options: HostStubGenOptions) { while (inEntries.hasMoreElements()) { val entry = inEntries.nextElement() convertSingleEntry(inZip, entry, stubOutStream, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) filter, packageRedirector, remapper, enableChecker, classes, errors, stats) } log.i("Converted all entries.") } Loading Loading @@ -253,6 +261,7 @@ class HostStubGen(val options: HostStubGenOptions) { implOutStream: ZipOutputStream?, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -270,7 +279,7 @@ class HostStubGen(val options: HostStubGenOptions) { // If it's a class, convert it. if (name.endsWith(".class")) { processSingleClass(inZip, entry, stubOutStream, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) packageRedirector, remapper, enableChecker, classes, errors, stats) return } Loading Loading @@ -321,6 +330,7 @@ class HostStubGen(val options: HostStubGenOptions) { implOutStream: ZipOutputStream?, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -332,16 +342,24 @@ class HostStubGen(val options: HostStubGenOptions) { log.d("Removing class: %s %s", classInternalName, classPolicy) return } // If we're applying a remapper, we need to rename the file too. var newName = entry.name remapper?.mapType(classInternalName)?.let { remappedName -> if (remappedName != classInternalName) { log.d("Renaming class file: %s -> %s", classInternalName, remappedName) newName = remappedName + ".class" } } // Generate stub first. if (stubOutStream != null && classPolicy.policy.needsInStub) { log.v("Creating stub class: %s Policy: %s", classInternalName, classPolicy) log.withIndent { BufferedInputStream(inZip.getInputStream(entry)).use { bis -> val newEntry = ZipEntry(entry.name) val newEntry = ZipEntry(newName) stubOutStream.putNextEntry(newEntry) convertClass(classInternalName, /*forImpl=*/false, bis, stubOutStream, filter, packageRedirector, enableChecker, classes, errors, null) stubOutStream, filter, packageRedirector, remapper, enableChecker, classes, errors, null) stubOutStream.closeEntry() } } Loading @@ -350,11 +368,11 @@ class HostStubGen(val options: HostStubGenOptions) { log.v("Creating impl class: %s Policy: %s", classInternalName, classPolicy) log.withIndent { BufferedInputStream(inZip.getInputStream(entry)).use { bis -> val newEntry = ZipEntry(entry.name) val newEntry = ZipEntry(newName) implOutStream.putNextEntry(newEntry) convertClass(classInternalName, /*forImpl=*/true, bis, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) implOutStream, filter, packageRedirector, remapper, enableChecker, classes, errors, stats) implOutStream.closeEntry() } } Loading @@ -371,6 +389,7 @@ class HostStubGen(val options: HostStubGenOptions) { out: OutputStream, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -387,6 +406,12 @@ class HostStubGen(val options: HostStubGenOptions) { if (enableChecker) { outVisitor = CheckClassAdapter(outVisitor) } // Remapping should happen at the end. remapper?.let { outVisitor = ClassRemapper(outVisitor, remapper) } val visitorOptions = BaseAdapter.Options( enablePreTrace = options.enablePreTrace.get, enablePostTrace = options.enablePostTrace.get, Loading @@ -395,7 +420,7 @@ class HostStubGen(val options: HostStubGenOptions) { stats = stats, ) outVisitor = BaseAdapter.getVisitor(classInternalName, classes, outVisitor, filter, packageRedirector, forImpl, visitorOptions) packageRedirector, remapper, forImpl, visitorOptions) cr.accept(outVisitor, ClassReader.EXPAND_FRAMES) val data = cw.toByteArray() Loading tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +29 −3 Original line number Diff line number Diff line Loading @@ -22,11 +22,13 @@ import com.android.hoststubgen.log import com.android.hoststubgen.normalizeTextLine import com.android.hoststubgen.whitespaceRegex import org.objectweb.asm.Opcodes import org.objectweb.asm.commons.Remapper import org.objectweb.asm.tree.ClassNode import java.io.BufferedReader import java.io.FileReader import java.io.PrintWriter import java.util.Objects import java.util.regex.Pattern /** * Print a class node as a "keep" policy. Loading Loading @@ -60,7 +62,7 @@ fun createFilterFromTextPolicyFile( filename: String, classes: ClassNodes, fallback: OutputFilter, ): OutputFilter { ): Pair<OutputFilter, Remapper?> { log.i("Loading offloaded annotations from $filename ...") log.withIndent { val subclassFilter = SubclassFilter(classes, fallback) Loading @@ -73,6 +75,7 @@ fun createFilterFromTextPolicyFile( var featureFlagsPolicy: FilterPolicyWithReason? = null var syspropsPolicy: FilterPolicyWithReason? = null var rFilePolicy: FilterPolicyWithReason? = null val typeRenameSpec = mutableListOf<TextFilePolicyRemapper.TypeRenameSpec>() try { BufferedReader(FileReader(filename)).use { reader -> Loading Loading @@ -251,6 +254,22 @@ fun createFilterFromTextPolicyFile( imf.setRenameTo(className, fromName, signature, name) } } "r", "rename" -> { if (fields.size < 3) { throw ParseException("Rename ('r') expects 2 fields.") } // Add ".*" to make it a prefix match. val pattern = Pattern.compile(fields[1] + ".*") // Removing the leading /'s from the prefix. This allows // using a single '/' as an empty suffix, which is useful to have a // "negative" rename rule to avoid subsequent raname's from getting // applied. (Which is needed for services.jar) val prefix = fields[2].trimStart('/') typeRenameSpec += TextFilePolicyRemapper.TypeRenameSpec( pattern, prefix) } else -> { throw ParseException("Unknown directive \"${fields[0]}\"") Loading @@ -262,9 +281,16 @@ fun createFilterFromTextPolicyFile( throw e.withSourceInfo(filename, lineNo) } var remapper: TextFilePolicyRemapper? = null if (typeRenameSpec.isNotEmpty()) { remapper = TextFilePolicyRemapper(typeRenameSpec) } // Wrap the in-memory-filter with AHF. return AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf) return Pair( AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf), remapper) } } Loading Loading
Ravenwood.bp +2 −1 Original line number Diff line number Diff line Loading @@ -159,7 +159,8 @@ java_library { "framework-minus-apex.ravenwood", ], sdk_version: "core_platform", jarjar_rules: ":ravenwood-framework-jarjar-rules", // See b/313930116. Jarjar is too slow on this jar. We use HostStubGen to do the rename. // jarjar_rules: ":ravenwood-framework-jarjar-rules", } java_genrule { Loading
ravenwood/texts/ravenwood-framework-jarjar-rules.txt +1 −2 Original line number Diff line number Diff line # To avoid VerifyError on nano proto files (b/324063814) rule com.**.nano.** devicenano.@0 # Applying jarjar on framework-minux-apex is too slow, so we don't use jarjar for now. b/313930116 No newline at end of file
ravenwood/texts/ravenwood-framework-policies.txt +5 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,11 @@ class :feature_flags keepclass # Keep all sysprops generated code implementations class :sysprops keepclass # To avoid VerifyError on nano proto files (b/324063814), we rename nano proto classes. # Note: The "rename" directive must use shashes (/) as a package name separator. rename com/.*/nano/ devicenano/ rename android/.*/nano/ devicenano/ # Exported to Mainline modules; cannot use annotations class com.android.internal.util.FastXmlSerializer keepclass class com.android.internal.util.FileRotator keepclass Loading
tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +39 −14 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import com.android.hoststubgen.visitors.PackageRedirectRemapper import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassVisitor import org.objectweb.asm.ClassWriter import org.objectweb.asm.commons.ClassRemapper import org.objectweb.asm.commons.Remapper import org.objectweb.asm.util.CheckClassAdapter import java.io.BufferedInputStream import java.io.FileOutputStream Loading Loading @@ -70,7 +72,7 @@ class HostStubGen(val options: HostStubGenOptions) { } // Build the filters. val filter = buildFilter(errors, allClasses, options) val (filter, policyFileRemapper) = buildFilter(errors, allClasses, options) // Transform the jar. convert( Loading @@ -82,6 +84,7 @@ class HostStubGen(val options: HostStubGenOptions) { allClasses, errors, stats, policyFileRemapper, ) // Dump statistics, if specified. Loading @@ -107,7 +110,7 @@ class HostStubGen(val options: HostStubGenOptions) { errors: HostStubGenErrors, allClasses: ClassNodes, options: HostStubGenOptions, ): OutputFilter { ): Pair<OutputFilter, Remapper?> { // We build a "chain" of multiple filters here. // // The filters are build in from "inside", meaning the first filter created here is Loading Loading @@ -160,10 +163,14 @@ class HostStubGen(val options: HostStubGenOptions) { filter, ) var policyFileRemapper: Remapper? = null // Next, "text based" filter, which allows to override polices without touching // the target code. options.policyOverrideFile.ifSet { filter = createFilterFromTextPolicyFile(it, allClasses, filter) val (f, p) = createFilterFromTextPolicyFile(it, allClasses, filter) filter = f policyFileRemapper = p } // If `--intersect-stub-jar` is provided, load from these jar files too. Loading @@ -178,7 +185,7 @@ class HostStubGen(val options: HostStubGenOptions) { // Apply the implicit filter. filter = ImplicitOutputFilter(errors, allClasses, filter) return filter return Pair(filter, policyFileRemapper) } /** Loading @@ -205,6 +212,7 @@ class HostStubGen(val options: HostStubGenOptions) { classes: ClassNodes, errors: HostStubGenErrors, stats: HostStubGenStats, remapper: Remapper?, ) { log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar) log.i("ASM CheckClassAdapter is %s", if (enableChecker) "enabled" else "disabled") Loading @@ -222,8 +230,8 @@ class HostStubGen(val options: HostStubGenOptions) { while (inEntries.hasMoreElements()) { val entry = inEntries.nextElement() convertSingleEntry(inZip, entry, stubOutStream, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) filter, packageRedirector, remapper, enableChecker, classes, errors, stats) } log.i("Converted all entries.") } Loading Loading @@ -253,6 +261,7 @@ class HostStubGen(val options: HostStubGenOptions) { implOutStream: ZipOutputStream?, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -270,7 +279,7 @@ class HostStubGen(val options: HostStubGenOptions) { // If it's a class, convert it. if (name.endsWith(".class")) { processSingleClass(inZip, entry, stubOutStream, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) packageRedirector, remapper, enableChecker, classes, errors, stats) return } Loading Loading @@ -321,6 +330,7 @@ class HostStubGen(val options: HostStubGenOptions) { implOutStream: ZipOutputStream?, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -332,16 +342,24 @@ class HostStubGen(val options: HostStubGenOptions) { log.d("Removing class: %s %s", classInternalName, classPolicy) return } // If we're applying a remapper, we need to rename the file too. var newName = entry.name remapper?.mapType(classInternalName)?.let { remappedName -> if (remappedName != classInternalName) { log.d("Renaming class file: %s -> %s", classInternalName, remappedName) newName = remappedName + ".class" } } // Generate stub first. if (stubOutStream != null && classPolicy.policy.needsInStub) { log.v("Creating stub class: %s Policy: %s", classInternalName, classPolicy) log.withIndent { BufferedInputStream(inZip.getInputStream(entry)).use { bis -> val newEntry = ZipEntry(entry.name) val newEntry = ZipEntry(newName) stubOutStream.putNextEntry(newEntry) convertClass(classInternalName, /*forImpl=*/false, bis, stubOutStream, filter, packageRedirector, enableChecker, classes, errors, null) stubOutStream, filter, packageRedirector, remapper, enableChecker, classes, errors, null) stubOutStream.closeEntry() } } Loading @@ -350,11 +368,11 @@ class HostStubGen(val options: HostStubGenOptions) { log.v("Creating impl class: %s Policy: %s", classInternalName, classPolicy) log.withIndent { BufferedInputStream(inZip.getInputStream(entry)).use { bis -> val newEntry = ZipEntry(entry.name) val newEntry = ZipEntry(newName) implOutStream.putNextEntry(newEntry) convertClass(classInternalName, /*forImpl=*/true, bis, implOutStream, filter, packageRedirector, enableChecker, classes, errors, stats) implOutStream, filter, packageRedirector, remapper, enableChecker, classes, errors, stats) implOutStream.closeEntry() } } Loading @@ -371,6 +389,7 @@ class HostStubGen(val options: HostStubGenOptions) { out: OutputStream, filter: OutputFilter, packageRedirector: PackageRedirectRemapper, remapper: Remapper?, enableChecker: Boolean, classes: ClassNodes, errors: HostStubGenErrors, Loading @@ -387,6 +406,12 @@ class HostStubGen(val options: HostStubGenOptions) { if (enableChecker) { outVisitor = CheckClassAdapter(outVisitor) } // Remapping should happen at the end. remapper?.let { outVisitor = ClassRemapper(outVisitor, remapper) } val visitorOptions = BaseAdapter.Options( enablePreTrace = options.enablePreTrace.get, enablePostTrace = options.enablePostTrace.get, Loading @@ -395,7 +420,7 @@ class HostStubGen(val options: HostStubGenOptions) { stats = stats, ) outVisitor = BaseAdapter.getVisitor(classInternalName, classes, outVisitor, filter, packageRedirector, forImpl, visitorOptions) packageRedirector, remapper, forImpl, visitorOptions) cr.accept(outVisitor, ClassReader.EXPAND_FRAMES) val data = cw.toByteArray() Loading
tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +29 −3 Original line number Diff line number Diff line Loading @@ -22,11 +22,13 @@ import com.android.hoststubgen.log import com.android.hoststubgen.normalizeTextLine import com.android.hoststubgen.whitespaceRegex import org.objectweb.asm.Opcodes import org.objectweb.asm.commons.Remapper import org.objectweb.asm.tree.ClassNode import java.io.BufferedReader import java.io.FileReader import java.io.PrintWriter import java.util.Objects import java.util.regex.Pattern /** * Print a class node as a "keep" policy. Loading Loading @@ -60,7 +62,7 @@ fun createFilterFromTextPolicyFile( filename: String, classes: ClassNodes, fallback: OutputFilter, ): OutputFilter { ): Pair<OutputFilter, Remapper?> { log.i("Loading offloaded annotations from $filename ...") log.withIndent { val subclassFilter = SubclassFilter(classes, fallback) Loading @@ -73,6 +75,7 @@ fun createFilterFromTextPolicyFile( var featureFlagsPolicy: FilterPolicyWithReason? = null var syspropsPolicy: FilterPolicyWithReason? = null var rFilePolicy: FilterPolicyWithReason? = null val typeRenameSpec = mutableListOf<TextFilePolicyRemapper.TypeRenameSpec>() try { BufferedReader(FileReader(filename)).use { reader -> Loading Loading @@ -251,6 +254,22 @@ fun createFilterFromTextPolicyFile( imf.setRenameTo(className, fromName, signature, name) } } "r", "rename" -> { if (fields.size < 3) { throw ParseException("Rename ('r') expects 2 fields.") } // Add ".*" to make it a prefix match. val pattern = Pattern.compile(fields[1] + ".*") // Removing the leading /'s from the prefix. This allows // using a single '/' as an empty suffix, which is useful to have a // "negative" rename rule to avoid subsequent raname's from getting // applied. (Which is needed for services.jar) val prefix = fields[2].trimStart('/') typeRenameSpec += TextFilePolicyRemapper.TypeRenameSpec( pattern, prefix) } else -> { throw ParseException("Unknown directive \"${fields[0]}\"") Loading @@ -262,9 +281,16 @@ fun createFilterFromTextPolicyFile( throw e.withSourceInfo(filename, lineNo) } var remapper: TextFilePolicyRemapper? = null if (typeRenameSpec.isNotEmpty()) { remapper = TextFilePolicyRemapper(typeRenameSpec) } // Wrap the in-memory-filter with AHF. return AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf) return Pair( AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf), remapper) } } Loading