Magisk/buildSrc/src/main/java/DesugarClassVisitorFactory.kt

75 lines
2.9 KiB
Kotlin
Raw Normal View History

2024-10-29 12:13:19 -07:00
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Opcodes.ASM9
2024-11-05 18:24:43 +08:00
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
2024-10-29 12:13:19 -07:00
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
2024-12-02 23:16:00 +08:00
private const val DESUGAR_GET_TIME_DESC =
"(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
2024-10-29 12:13:19 -07:00
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor
): ClassVisitor {
2024-12-02 23:16:00 +08:00
return DesugarClassVisitor(classContext, nextClassVisitor)
2024-10-29 12:13:19 -07:00
}
2024-11-05 18:24:43 +08:00
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
2024-10-29 12:13:19 -07:00
2024-12-02 23:16:00 +08:00
class DesugarClassVisitor(private val classContext: ClassContext, cv: ClassVisitor) :
ClassVisitor(ASM9, cv) {
2024-10-29 12:13:19 -07:00
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
2024-12-02 23:16:00 +08:00
return DesugarMethodVisitor(
super.visitMethod(access, name, descriptor, signature, exceptions)
)
2024-10-29 12:13:19 -07:00
}
2024-12-02 23:16:00 +08:00
inner class DesugarMethodVisitor(mv: MethodVisitor?) :
MethodVisitor(ASM9, mv) {
override fun visitMethodInsn(
opcode: Int,
owner: String,
name: String,
descriptor: String,
isInterface: Boolean
) {
if (!classContext.loadClassData(owner.replace("/", "."))?.superClasses.orEmpty()
.contains("java.util.zip.ZipEntry") || !process(name, descriptor)
) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
}
2024-10-29 12:13:19 -07:00
}
2024-12-02 23:16:00 +08:00
private fun process(name: String, descriptor: String): Boolean {
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
return false
return when (name) {
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
DESUGAR_CLASS_NAME.replace('.', '/'),
name,
DESUGAR_GET_TIME_DESC,
false
)
true
}
else -> false
2024-10-29 12:13:19 -07:00
}
}
}
}
}