Skip to content

Commit

Permalink
Add our own API desugaring
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed Oct 29, 2024
1 parent 455b13b commit f4502f8
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
11 changes: 11 additions & 0 deletions app/apk/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import com.android.build.api.instrumentation.FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
import com.android.build.api.instrumentation.InstrumentationScope

plugins {
id("com.android.application")
kotlin("android")
Expand Down Expand Up @@ -46,6 +49,14 @@ android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}

androidComponents {
onVariants {
it.instrumentation.setAsmFramesComputationMode(COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS)
it.instrumentation.transformClassesWith(
DesugarClassVisitorFactory::class.java, InstrumentationScope.ALL) {}
}
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.topjohnwu.magisk.core.utils;

import android.os.Build;

import java.nio.file.attribute.FileTime;
import java.util.zip.ZipEntry;

public class Desugar {
public static FileTime getLastModifiedTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getLastModifiedTime();
} else {
return FileTime.fromMillis(entry.getTime());
}
}

public static FileTime getLastAccessTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getLastAccessTime();
} else {
return null;
}
}

public static FileTime getCreationTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getCreationTime();
} else {
return null;
}
}
}
67 changes: 67 additions & 0 deletions buildSrc/src/main/java/DesugarClassVisitorFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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

private const val DESUGAR_CLASS_NAME = "com/topjohnwu/magisk/core/utils/Desugar"
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
private const val DESUGAR_GET_TIME_DESC = "(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"

abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor
): ClassVisitor {
return DesugarClassVisitor(nextClassVisitor)
}

override fun isInstrumentable(classData: ClassData) = true

class DesugarClassVisitor(cv: ClassVisitor) : ClassVisitor(ASM9, cv) {
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
return DesugarMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions))
}
}

class DesugarMethodVisitor(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
override fun visitMethodInsn(
opcode: Int,
owner: String,
name: String,
descriptor: String,
isInterface: Boolean
) {
if (!process(name, descriptor)) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
}
}

private fun process(name: String, descriptor: String): Boolean {
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
return false
when (name) {
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
DESUGAR_CLASS_NAME,
name,
DESUGAR_GET_TIME_DESC,
false
)
}
else -> return false
}
return true
}
}
}

0 comments on commit f4502f8

Please sign in to comment.