Loading ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/HostStubGenClassProcessor.kt +56 −20 Original line number Diff line number Diff line Loading @@ -30,12 +30,15 @@ import com.android.hoststubgen.filters.TextFileFilterPolicyBuilder import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep import com.android.hoststubgen.utils.ClassPredicate import com.android.hoststubgen.visitors.BaseAdapter import com.android.hoststubgen.visitors.ImplGeneratingAdapter import com.android.hoststubgen.visitors.PackageRedirectRemapper import java.io.PrintWriter 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.util.CheckClassAdapter import org.objectweb.asm.util.TraceClassVisitor /** * This class implements bytecode transformation of HostStubGen. Loading Loading @@ -133,21 +136,10 @@ class HostStubGenClassProcessor( return filter } fun processClassBytecode(bytecode: ByteArray): ByteArray { val cr = ClassReader(bytecode) // If the class was already processed previously, skip val clz = allClasses.getClass(cr.className) if (clz.findAnyAnnotation(processedAnnotation) != null) { return bytecode } private fun buildVisitor(base: ClassVisitor, className: String): ClassVisitor { // Connect to the base visitor var outVisitor: ClassVisitor = base // COMPUTE_FRAMES wouldn't be happy if code uses val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES val cw = ClassWriter(flags) // Connect to the class writer var outVisitor: ClassVisitor = cw if (options.enableClassChecker.get) { outVisitor = CheckClassAdapter(outVisitor) } Loading @@ -158,15 +150,59 @@ class HostStubGenClassProcessor( val visitorOptions = BaseAdapter.Options( errors = errors, stats = stats, enablePreTrace = options.enablePreTrace.get, enablePostTrace = options.enablePostTrace.get, deleteClassFinals = options.deleteFinals.get, deleteMethodFinals = options.deleteFinals.get, ) outVisitor = BaseAdapter.getVisitor( cr.className, allClasses, outVisitor, filter, packageRedirector, visitorOptions val verbosePrinter = PrintWriter(log.getWriter(LogLevel.Verbose)) // Inject TraceClassVisitor for debugging. if (options.enablePostTrace.get) { outVisitor = TraceClassVisitor(outVisitor, verbosePrinter) } // Handle --package-redirect if (!packageRedirector.isEmpty) { // Don't apply the remapper on redirect-from classes. // Otherwise, if the target jar actually contains the "from" classes (which // may or may not be the case) they'd be renamed. // But we update all references in other places, so, a method call to a "from" class // would be replaced with the "to" class. All type references (e.g. variable types) // will be updated too. if (!packageRedirector.isTarget(className)) { outVisitor = ClassRemapper(outVisitor, packageRedirector) } else { log.v( "Class $className is a redirect-from class, not applying" + " --package-redirect" ) } } outVisitor = ImplGeneratingAdapter(allClasses, outVisitor, filter, visitorOptions) // Inject TraceClassVisitor for debugging. if (options.enablePreTrace.get) { outVisitor = TraceClassVisitor(outVisitor, verbosePrinter) } return outVisitor } fun processClassBytecode(bytecode: ByteArray): ByteArray { val cr = ClassReader(bytecode) // If the class was already processed previously, skip val clz = allClasses.getClass(cr.className) if (clz.findAnyAnnotation(processedAnnotation) != null) { return bytecode } // COMPUTE_FRAMES wouldn't be happy if code uses val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES val cw = ClassWriter(flags) val outVisitor = buildVisitor(cw, cr.className) cr.accept(outVisitor, ClassReader.EXPAND_FRAMES) return cw.toByteArray() Loading ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/DelegatingFilter.kt +13 −14 Original line number Diff line number Diff line Loading @@ -97,13 +97,12 @@ abstract class DelegatingFilter( } override fun getMethodCallReplaceTo( callerClassName: String, callerMethodName: String, className: String, methodName: String, descriptor: String, ): MethodReplaceTarget? { return fallback.getMethodCallReplaceTo( callerClassName, callerMethodName, className, methodName, descriptor) className, methodName, descriptor ) } } ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/InMemoryOutputFilter.kt +64 −21 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ class InMemoryOutputFilter( private val classes: ClassNodes, fallback: OutputFilter, ) : DelegatingFilter(fallback) { private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf() private val mRenames: MutableMap<String, String> = mutableMapOf() private val mRedirectionClasses: MutableMap<String, String> = mutableMapOf() private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf() private val mPolicies = mutableMapOf<String, FilterPolicyWithReason>() private val mRenames = mutableMapOf<String, String>() private val mRedirectionClasses = mutableMapOf<String, String>() private val mClassLoadHooks = mutableMapOf<String, String>() private val mMethodCallReplaceSpecs = mutableListOf<MethodCallReplaceSpec>() private val mTypeRenameSpecs = mutableListOf<TypeRenameSpec>() private fun getClassKey(className: String): String { return className.toHumanReadableClassName() Loading @@ -45,10 +47,6 @@ class InMemoryOutputFilter( return getClassKey(className) + "." + methodName + ";" + signature } override fun getPolicyForClass(className: String): FilterPolicyWithReason { return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) } private fun checkClass(className: String) { if (classes.findClass(className) == null) { log.w("Unknown class $className") Loading @@ -74,6 +72,10 @@ class InMemoryOutputFilter( } } override fun getPolicyForClass(className: String): FilterPolicyWithReason { return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) } fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) { checkClass(className) mPolicies[getClassKey(className)] = policy Loading Loading @@ -135,11 +137,52 @@ class InMemoryOutputFilter( } override fun getClassLoadHooks(className: String): List<String> { return addNonNullElement(super.getClassLoadHooks(className), mClassLoadHooks[getClassKey(className)]) return addNonNullElement( super.getClassLoadHooks(className), mClassLoadHooks[getClassKey(className)] ) } fun setClassLoadHook(className: String, methodName: String) { mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName() } override fun hasAnyMethodCallReplace(): Boolean { return mMethodCallReplaceSpecs.isNotEmpty() || super.hasAnyMethodCallReplace() } override fun getMethodCallReplaceTo( className: String, methodName: String, descriptor: String, ): MethodReplaceTarget? { // Maybe use 'Tri' if we end up having too many replacements. mMethodCallReplaceSpecs.forEach { if (className == it.fromClass && methodName == it.fromMethod ) { if (it.fromDescriptor == "*" || descriptor == it.fromDescriptor) { return MethodReplaceTarget(it.toClass, it.toMethod) } } } return super.getMethodCallReplaceTo(className, methodName, descriptor) } fun setMethodCallReplaceSpec(spec: MethodCallReplaceSpec) { mMethodCallReplaceSpecs.add(spec) } override fun remapType(className: String): String? { mTypeRenameSpecs.forEach { if (it.typeInternalNamePattern.matcher(className).matches()) { return it.typeInternalNamePrefix + className } } return super.remapType(className) } fun setRemapTypeSpec(spec: TypeRenameSpec) { mTypeRenameSpecs.add(spec) } } ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/OutputFilter.kt +4 −6 Original line number Diff line number Diff line Loading @@ -108,8 +108,6 @@ abstract class OutputFilter { * If a method call should be forwarded to another method, return the target's class / method. */ open fun getMethodCallReplaceTo( callerClassName: String, callerMethodName: String, className: String, methodName: String, descriptor: String, Loading ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +33 −34 Original line number Diff line number Diff line Loading @@ -58,6 +58,23 @@ enum class SpecialClass { RFile, } data class MethodCallReplaceSpec( val fromClass: String, val fromMethod: String, val fromDescriptor: String, val toClass: String, val toMethod: String, ) /** * When a package name matches [typeInternalNamePattern], we prepend [typeInternalNamePrefix] * to it. */ data class TypeRenameSpec( val typeInternalNamePattern: Pattern, val typeInternalNamePrefix: String, ) /** * This receives [TextFileFilterPolicyBuilder] parsing result. */ Loading Loading @@ -99,7 +116,7 @@ interface PolicyFileProcessor { className: String, methodName: String, methodDesc: String, replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec, replaceSpec: MethodCallReplaceSpec, ) } Loading @@ -116,9 +133,6 @@ class TextFileFilterPolicyBuilder( private var featureFlagsPolicy: FilterPolicyWithReason? = null private var syspropsPolicy: FilterPolicyWithReason? = null private var rFilePolicy: FilterPolicyWithReason? = null private val typeRenameSpec = mutableListOf<TextFilePolicyRemapperFilter.TypeRenameSpec>() private val methodReplaceSpec = mutableListOf<TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec>() /** * Fields for a filter chain used for "partial allowlisting", which are used by Loading @@ -126,17 +140,14 @@ class TextFileFilterPolicyBuilder( */ private val annotationAllowedInMemoryFilter: InMemoryOutputFilter val annotationAllowedMembersFilter: OutputFilter get() = annotationAllowedInMemoryFilter private val annotationAllowedPolicy = FilterPolicy.AnnotationAllowed.withReason(FILTER_REASON) init { // Create a filter that checks "partial allowlisting". var aaf: OutputFilter = ConstantFilter(FilterPolicy.Remove, "default disallowed") aaf = InMemoryOutputFilter(classes, aaf) annotationAllowedInMemoryFilter = aaf annotationAllowedMembersFilter = annotationAllowedInMemoryFilter val filter = ConstantFilter(FilterPolicy.Remove, "default disallowed") annotationAllowedInMemoryFilter = InMemoryOutputFilter(classes, filter) } /** Loading @@ -153,20 +164,10 @@ class TextFileFilterPolicyBuilder( * Generate the resulting [OutputFilter]. */ fun createOutputFilter(): OutputFilter { var ret: OutputFilter = imf if (typeRenameSpec.isNotEmpty()) { ret = TextFilePolicyRemapperFilter(typeRenameSpec, ret) } if (methodReplaceSpec.isNotEmpty()) { ret = TextFilePolicyMethodReplaceFilter(methodReplaceSpec, classes, ret) } // Wrap the in-memory-filter with AHF. ret = AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, ret return AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf ) return ret } private inner class Processor : PolicyFileProcessor { Loading @@ -180,9 +181,7 @@ class TextFileFilterPolicyBuilder( } override fun onRename(pattern: Pattern, prefix: String) { typeRenameSpec += TextFilePolicyRemapperFilter.TypeRenameSpec( pattern, prefix ) imf.setRemapTypeSpec(TypeRenameSpec(pattern, prefix)) } override fun onClassStart(className: String) { Loading Loading @@ -284,12 +283,12 @@ class TextFileFilterPolicyBuilder( className: String, methodName: String, methodDesc: String, replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec, replaceSpec: MethodCallReplaceSpec, ) { // Keep the source method, because the target method may call it. imf.setPolicyForMethod(className, methodName, methodDesc, FilterPolicy.Keep.withReason(FILTER_REASON)) methodReplaceSpec.add(replaceSpec) imf.setMethodCallReplaceSpec(replaceSpec) } } } Loading Loading @@ -630,8 +629,8 @@ class TextFileFilterPolicyParser { if (classAndMethod != null) { // If the substitution target contains a ".", then // it's a method call redirect. val spec = TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec( currentClassName!!.toJvmClassName(), val spec = MethodCallReplaceSpec( className.toJvmClassName(), methodName, signature, classAndMethod.first.toJvmClassName(), Loading Loading
ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/HostStubGenClassProcessor.kt +56 −20 Original line number Diff line number Diff line Loading @@ -30,12 +30,15 @@ import com.android.hoststubgen.filters.TextFileFilterPolicyBuilder import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep import com.android.hoststubgen.utils.ClassPredicate import com.android.hoststubgen.visitors.BaseAdapter import com.android.hoststubgen.visitors.ImplGeneratingAdapter import com.android.hoststubgen.visitors.PackageRedirectRemapper import java.io.PrintWriter 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.util.CheckClassAdapter import org.objectweb.asm.util.TraceClassVisitor /** * This class implements bytecode transformation of HostStubGen. Loading Loading @@ -133,21 +136,10 @@ class HostStubGenClassProcessor( return filter } fun processClassBytecode(bytecode: ByteArray): ByteArray { val cr = ClassReader(bytecode) // If the class was already processed previously, skip val clz = allClasses.getClass(cr.className) if (clz.findAnyAnnotation(processedAnnotation) != null) { return bytecode } private fun buildVisitor(base: ClassVisitor, className: String): ClassVisitor { // Connect to the base visitor var outVisitor: ClassVisitor = base // COMPUTE_FRAMES wouldn't be happy if code uses val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES val cw = ClassWriter(flags) // Connect to the class writer var outVisitor: ClassVisitor = cw if (options.enableClassChecker.get) { outVisitor = CheckClassAdapter(outVisitor) } Loading @@ -158,15 +150,59 @@ class HostStubGenClassProcessor( val visitorOptions = BaseAdapter.Options( errors = errors, stats = stats, enablePreTrace = options.enablePreTrace.get, enablePostTrace = options.enablePostTrace.get, deleteClassFinals = options.deleteFinals.get, deleteMethodFinals = options.deleteFinals.get, ) outVisitor = BaseAdapter.getVisitor( cr.className, allClasses, outVisitor, filter, packageRedirector, visitorOptions val verbosePrinter = PrintWriter(log.getWriter(LogLevel.Verbose)) // Inject TraceClassVisitor for debugging. if (options.enablePostTrace.get) { outVisitor = TraceClassVisitor(outVisitor, verbosePrinter) } // Handle --package-redirect if (!packageRedirector.isEmpty) { // Don't apply the remapper on redirect-from classes. // Otherwise, if the target jar actually contains the "from" classes (which // may or may not be the case) they'd be renamed. // But we update all references in other places, so, a method call to a "from" class // would be replaced with the "to" class. All type references (e.g. variable types) // will be updated too. if (!packageRedirector.isTarget(className)) { outVisitor = ClassRemapper(outVisitor, packageRedirector) } else { log.v( "Class $className is a redirect-from class, not applying" + " --package-redirect" ) } } outVisitor = ImplGeneratingAdapter(allClasses, outVisitor, filter, visitorOptions) // Inject TraceClassVisitor for debugging. if (options.enablePreTrace.get) { outVisitor = TraceClassVisitor(outVisitor, verbosePrinter) } return outVisitor } fun processClassBytecode(bytecode: ByteArray): ByteArray { val cr = ClassReader(bytecode) // If the class was already processed previously, skip val clz = allClasses.getClass(cr.className) if (clz.findAnyAnnotation(processedAnnotation) != null) { return bytecode } // COMPUTE_FRAMES wouldn't be happy if code uses val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES val cw = ClassWriter(flags) val outVisitor = buildVisitor(cw, cr.className) cr.accept(outVisitor, ClassReader.EXPAND_FRAMES) return cw.toByteArray() Loading
ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/DelegatingFilter.kt +13 −14 Original line number Diff line number Diff line Loading @@ -97,13 +97,12 @@ abstract class DelegatingFilter( } override fun getMethodCallReplaceTo( callerClassName: String, callerMethodName: String, className: String, methodName: String, descriptor: String, ): MethodReplaceTarget? { return fallback.getMethodCallReplaceTo( callerClassName, callerMethodName, className, methodName, descriptor) className, methodName, descriptor ) } }
ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/InMemoryOutputFilter.kt +64 −21 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ class InMemoryOutputFilter( private val classes: ClassNodes, fallback: OutputFilter, ) : DelegatingFilter(fallback) { private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf() private val mRenames: MutableMap<String, String> = mutableMapOf() private val mRedirectionClasses: MutableMap<String, String> = mutableMapOf() private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf() private val mPolicies = mutableMapOf<String, FilterPolicyWithReason>() private val mRenames = mutableMapOf<String, String>() private val mRedirectionClasses = mutableMapOf<String, String>() private val mClassLoadHooks = mutableMapOf<String, String>() private val mMethodCallReplaceSpecs = mutableListOf<MethodCallReplaceSpec>() private val mTypeRenameSpecs = mutableListOf<TypeRenameSpec>() private fun getClassKey(className: String): String { return className.toHumanReadableClassName() Loading @@ -45,10 +47,6 @@ class InMemoryOutputFilter( return getClassKey(className) + "." + methodName + ";" + signature } override fun getPolicyForClass(className: String): FilterPolicyWithReason { return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) } private fun checkClass(className: String) { if (classes.findClass(className) == null) { log.w("Unknown class $className") Loading @@ -74,6 +72,10 @@ class InMemoryOutputFilter( } } override fun getPolicyForClass(className: String): FilterPolicyWithReason { return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) } fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) { checkClass(className) mPolicies[getClassKey(className)] = policy Loading Loading @@ -135,11 +137,52 @@ class InMemoryOutputFilter( } override fun getClassLoadHooks(className: String): List<String> { return addNonNullElement(super.getClassLoadHooks(className), mClassLoadHooks[getClassKey(className)]) return addNonNullElement( super.getClassLoadHooks(className), mClassLoadHooks[getClassKey(className)] ) } fun setClassLoadHook(className: String, methodName: String) { mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName() } override fun hasAnyMethodCallReplace(): Boolean { return mMethodCallReplaceSpecs.isNotEmpty() || super.hasAnyMethodCallReplace() } override fun getMethodCallReplaceTo( className: String, methodName: String, descriptor: String, ): MethodReplaceTarget? { // Maybe use 'Tri' if we end up having too many replacements. mMethodCallReplaceSpecs.forEach { if (className == it.fromClass && methodName == it.fromMethod ) { if (it.fromDescriptor == "*" || descriptor == it.fromDescriptor) { return MethodReplaceTarget(it.toClass, it.toMethod) } } } return super.getMethodCallReplaceTo(className, methodName, descriptor) } fun setMethodCallReplaceSpec(spec: MethodCallReplaceSpec) { mMethodCallReplaceSpecs.add(spec) } override fun remapType(className: String): String? { mTypeRenameSpecs.forEach { if (it.typeInternalNamePattern.matcher(className).matches()) { return it.typeInternalNamePrefix + className } } return super.remapType(className) } fun setRemapTypeSpec(spec: TypeRenameSpec) { mTypeRenameSpecs.add(spec) } }
ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/OutputFilter.kt +4 −6 Original line number Diff line number Diff line Loading @@ -108,8 +108,6 @@ abstract class OutputFilter { * If a method call should be forwarded to another method, return the target's class / method. */ open fun getMethodCallReplaceTo( callerClassName: String, callerMethodName: String, className: String, methodName: String, descriptor: String, Loading
ravenwood/tools/hoststubgen/lib/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +33 −34 Original line number Diff line number Diff line Loading @@ -58,6 +58,23 @@ enum class SpecialClass { RFile, } data class MethodCallReplaceSpec( val fromClass: String, val fromMethod: String, val fromDescriptor: String, val toClass: String, val toMethod: String, ) /** * When a package name matches [typeInternalNamePattern], we prepend [typeInternalNamePrefix] * to it. */ data class TypeRenameSpec( val typeInternalNamePattern: Pattern, val typeInternalNamePrefix: String, ) /** * This receives [TextFileFilterPolicyBuilder] parsing result. */ Loading Loading @@ -99,7 +116,7 @@ interface PolicyFileProcessor { className: String, methodName: String, methodDesc: String, replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec, replaceSpec: MethodCallReplaceSpec, ) } Loading @@ -116,9 +133,6 @@ class TextFileFilterPolicyBuilder( private var featureFlagsPolicy: FilterPolicyWithReason? = null private var syspropsPolicy: FilterPolicyWithReason? = null private var rFilePolicy: FilterPolicyWithReason? = null private val typeRenameSpec = mutableListOf<TextFilePolicyRemapperFilter.TypeRenameSpec>() private val methodReplaceSpec = mutableListOf<TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec>() /** * Fields for a filter chain used for "partial allowlisting", which are used by Loading @@ -126,17 +140,14 @@ class TextFileFilterPolicyBuilder( */ private val annotationAllowedInMemoryFilter: InMemoryOutputFilter val annotationAllowedMembersFilter: OutputFilter get() = annotationAllowedInMemoryFilter private val annotationAllowedPolicy = FilterPolicy.AnnotationAllowed.withReason(FILTER_REASON) init { // Create a filter that checks "partial allowlisting". var aaf: OutputFilter = ConstantFilter(FilterPolicy.Remove, "default disallowed") aaf = InMemoryOutputFilter(classes, aaf) annotationAllowedInMemoryFilter = aaf annotationAllowedMembersFilter = annotationAllowedInMemoryFilter val filter = ConstantFilter(FilterPolicy.Remove, "default disallowed") annotationAllowedInMemoryFilter = InMemoryOutputFilter(classes, filter) } /** Loading @@ -153,20 +164,10 @@ class TextFileFilterPolicyBuilder( * Generate the resulting [OutputFilter]. */ fun createOutputFilter(): OutputFilter { var ret: OutputFilter = imf if (typeRenameSpec.isNotEmpty()) { ret = TextFilePolicyRemapperFilter(typeRenameSpec, ret) } if (methodReplaceSpec.isNotEmpty()) { ret = TextFilePolicyMethodReplaceFilter(methodReplaceSpec, classes, ret) } // Wrap the in-memory-filter with AHF. ret = AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, ret return AndroidHeuristicsFilter( classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf ) return ret } private inner class Processor : PolicyFileProcessor { Loading @@ -180,9 +181,7 @@ class TextFileFilterPolicyBuilder( } override fun onRename(pattern: Pattern, prefix: String) { typeRenameSpec += TextFilePolicyRemapperFilter.TypeRenameSpec( pattern, prefix ) imf.setRemapTypeSpec(TypeRenameSpec(pattern, prefix)) } override fun onClassStart(className: String) { Loading Loading @@ -284,12 +283,12 @@ class TextFileFilterPolicyBuilder( className: String, methodName: String, methodDesc: String, replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec, replaceSpec: MethodCallReplaceSpec, ) { // Keep the source method, because the target method may call it. imf.setPolicyForMethod(className, methodName, methodDesc, FilterPolicy.Keep.withReason(FILTER_REASON)) methodReplaceSpec.add(replaceSpec) imf.setMethodCallReplaceSpec(replaceSpec) } } } Loading Loading @@ -630,8 +629,8 @@ class TextFileFilterPolicyParser { if (classAndMethod != null) { // If the substitution target contains a ".", then // it's a method call redirect. val spec = TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec( currentClassName!!.toJvmClassName(), val spec = MethodCallReplaceSpec( className.toJvmClassName(), methodName, signature, classAndMethod.first.toJvmClassName(), Loading