diff --git a/patcher/build.gradle.kts b/patcher/build.gradle.kts index cb1f419..eb1f636 100644 --- a/patcher/build.gradle.kts +++ b/patcher/build.gradle.kts @@ -1,5 +1,5 @@ + import com.android.build.api.dsl.androidLibrary -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation plugins { @@ -33,12 +33,6 @@ kotlin { withDeviceTestBuilder { sourceSetTreeName = "test" } - - compilations.configureEach { - compilerOptions.configure { - jvmTarget.set(JvmTarget.JVM_11) - } - } } sourceSets { @@ -61,6 +55,8 @@ kotlin { "-Xexplicit-backing-fields", "-Xcontext-parameters", ) + + jvmToolchain(11) } } diff --git a/patcher/src/androidMain/kotlin/app/revanced/collections/MutableMap.android.kt b/patcher/src/androidMain/kotlin/app/revanced/collections/MutableMap.android.kt new file mode 100644 index 0000000..95b61ce --- /dev/null +++ b/patcher/src/androidMain/kotlin/app/revanced/collections/MutableMap.android.kt @@ -0,0 +1,7 @@ +package app.revanced.collections + +actual fun MutableMap.kmpMerge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V, +) = MutableMap::merge.call(key, value, remappingFunction) as Unit diff --git a/patcher/src/androidMain/kotlin/java/io/File.android.kt b/patcher/src/androidMain/kotlin/app/revanced/java/io/File.android.kt similarity index 79% rename from patcher/src/androidMain/kotlin/java/io/File.android.kt rename to patcher/src/androidMain/kotlin/app/revanced/java/io/File.android.kt index 9f4d938..69cf201 100644 --- a/patcher/src/androidMain/kotlin/java/io/File.android.kt +++ b/patcher/src/androidMain/kotlin/app/revanced/java/io/File.android.kt @@ -1,8 +1,12 @@ -package java.io +package app.revanced.java.io +import java.io.File import java.nio.charset.Charset internal actual fun File.kmpResolve(child: String) = resolve(child) + internal actual fun File.kmpDeleteRecursively() = deleteRecursively() + internal actual fun File.kmpInputStream() = inputStream() -internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) \ No newline at end of file + +internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) diff --git a/patcher/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt b/patcher/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt index 698316d..2866225 100644 --- a/patcher/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt +++ b/patcher/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt @@ -25,7 +25,9 @@ actual fun loadPatches( ) = loadPatches( patchesFiles = patchesFiles, { patchBundle -> - MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes + MultiDexIO + .readDexFile(true, patchBundle, BasicDexFileNamer(), null, null) + .classes .map { classDef -> classDef.type.substring(1, classDef.length - 1) } @@ -33,7 +35,11 @@ actual fun loadPatches( DexClassLoader( patchesFiles.joinToString(File.pathSeparator) { it.absolutePath }, null, - null, null + null, + null, ), - onFailedToLoad + onFailedToLoad, ) + +@Suppress("NOTHING_TO_INLINE") +actual inline val currentClassLoader get() = object {}::class.java.classLoader diff --git a/patcher/src/androidMain/kotlin/collections/MutableMap.android.kt b/patcher/src/androidMain/kotlin/collections/MutableMap.android.kt deleted file mode 100644 index 8ff5cb0..0000000 --- a/patcher/src/androidMain/kotlin/collections/MutableMap.android.kt +++ /dev/null @@ -1,7 +0,0 @@ -package collections - -actual fun MutableMap.kmpMerge( - key: K, - value: V, - remappingFunction: (oldValue: V, newValue: V) -> V -) = merge(key, value, remappingFunction) \ No newline at end of file diff --git a/patcher/src/commonMain/kotlin/collections/MutableMap.kt b/patcher/src/commonMain/kotlin/app/revanced/collections/MutableMap.kt similarity index 77% rename from patcher/src/commonMain/kotlin/collections/MutableMap.kt rename to patcher/src/commonMain/kotlin/app/revanced/collections/MutableMap.kt index 1a66170..b28626d 100644 --- a/patcher/src/commonMain/kotlin/collections/MutableMap.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/collections/MutableMap.kt @@ -1,4 +1,4 @@ -package collections +package app.revanced.collections internal expect fun MutableMap.kmpMerge( key: K, @@ -10,4 +10,4 @@ internal fun MutableMap.merge( key: K, value: V, remappingFunction: (oldValue: V, newValue: V) -> V, -) = kmpMerge(key, value, remappingFunction) \ No newline at end of file +) = kmpMerge(key, value, remappingFunction) diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt similarity index 61% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt index 99d1a64..dab8858 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt @@ -1,10 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable import com.android.tools.smali.dexlib2.base.value.BaseAnnotationEncodedValue -import com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable +import com.android.tools.smali.dexlib2.iface.value.AnnotationEncodedValue -class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedValue) : - BaseAnnotationEncodedValue(), +class MutableAnnotationEncodedValue( + annotationEncodedValue: AnnotationEncodedValue, +) : BaseAnnotationEncodedValue(), MutableEncodedValue { private var type = annotationEncodedValue.type diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt similarity index 50% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt index 97363b1..f45968a 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt @@ -1,9 +1,13 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value +import app.revanced.com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue -import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable +import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue -class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : BaseArrayEncodedValue(), MutableEncodedValue { +class MutableArrayEncodedValue( + arrayEncodedValue: ArrayEncodedValue, +) : BaseArrayEncodedValue(), + MutableEncodedValue { private val _value by lazy { arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList() } diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt similarity index 62% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt index ca24cb7..220f247 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt @@ -1,9 +1,11 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseBooleanEncodedValue +import com.android.tools.smali.dexlib2.iface.value.BooleanEncodedValue -class MutableBooleanEncodedValue(booleanEncodedValue: BooleanEncodedValue) : - BaseBooleanEncodedValue(), +class MutableBooleanEncodedValue( + booleanEncodedValue: BooleanEncodedValue, +) : BaseBooleanEncodedValue(), MutableEncodedValue { private var value = booleanEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt index 82b04c0..fa5780e 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseByteEncodedValue +import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue -class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) : BaseByteEncodedValue(), MutableEncodedValue { +class MutableByteEncodedValue( + byteEncodedValue: ByteEncodedValue, +) : BaseByteEncodedValue(), + MutableEncodedValue { private var value = byteEncodedValue.value fun setValue(value: Byte) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt index eef4676..cc4bdd8 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseCharEncodedValue +import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue -class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) : BaseCharEncodedValue(), MutableEncodedValue { +class MutableCharEncodedValue( + charEncodedValue: CharEncodedValue, +) : BaseCharEncodedValue(), + MutableEncodedValue { private var value = charEncodedValue.value fun setValue(value: Char) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt similarity index 62% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt index 6259ec2..6aef2a1 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt @@ -1,9 +1,11 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseDoubleEncodedValue +import com.android.tools.smali.dexlib2.iface.value.DoubleEncodedValue -class MutableDoubleEncodedValue(doubleEncodedValue: DoubleEncodedValue) : - BaseDoubleEncodedValue(), +class MutableDoubleEncodedValue( + doubleEncodedValue: DoubleEncodedValue, +) : BaseDoubleEncodedValue(), MutableEncodedValue { private var value = doubleEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt similarity index 89% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt index bf3112b..8ab6b3d 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt @@ -1,11 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.ValueType +import com.android.tools.smali.dexlib2.iface.value.* interface MutableEncodedValue : EncodedValue { companion object { - fun EncodedValue.toMutable(): MutableEncodedValue { - return when (this.valueType) { + fun EncodedValue.toMutable(): MutableEncodedValue = + when (this.valueType) { ValueType.TYPE -> MutableTypeEncodedValue(this as TypeEncodedValue) ValueType.FIELD -> MutableFieldEncodedValue(this as FieldEncodedValue) ValueType.METHOD -> MutableMethodEncodedValue(this as MethodEncodedValue) @@ -26,6 +27,5 @@ interface MutableEncodedValue : EncodedValue { ValueType.NULL -> MutableNullEncodedValue() else -> this as MutableEncodedValue } - } } } diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt similarity index 63% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt index 5c41b7d..7ddbd8b 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt @@ -1,9 +1,13 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseEnumEncodedValue import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.value.EnumEncodedValue -class MutableEnumEncodedValue(enumEncodedValue: EnumEncodedValue) : BaseEnumEncodedValue(), MutableEncodedValue { +class MutableEnumEncodedValue( + enumEncodedValue: EnumEncodedValue, +) : BaseEnumEncodedValue(), + MutableEncodedValue { private var value = enumEncodedValue.value fun setValue(value: FieldReference) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt similarity index 68% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt index 14d1144..9f86646 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt @@ -1,10 +1,14 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.ValueType import com.android.tools.smali.dexlib2.base.value.BaseFieldEncodedValue import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.value.FieldEncodedValue -class MutableFieldEncodedValue(fieldEncodedValue: FieldEncodedValue) : BaseFieldEncodedValue(), MutableEncodedValue { +class MutableFieldEncodedValue( + fieldEncodedValue: FieldEncodedValue, +) : BaseFieldEncodedValue(), + MutableEncodedValue { private var value = fieldEncodedValue.value fun setValue(value: FieldReference) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt index 9d23b6b..d3ed026 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseFloatEncodedValue +import com.android.tools.smali.dexlib2.iface.value.FloatEncodedValue -class MutableFloatEncodedValue(floatEncodedValue: FloatEncodedValue) : BaseFloatEncodedValue(), MutableEncodedValue { +class MutableFloatEncodedValue( + floatEncodedValue: FloatEncodedValue, +) : BaseFloatEncodedValue(), + MutableEncodedValue { private var value = floatEncodedValue.value fun setValue(value: Float) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt index e035b1f..9940309 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseIntEncodedValue +import com.android.tools.smali.dexlib2.iface.value.IntEncodedValue -class MutableIntEncodedValue(intEncodedValue: IntEncodedValue) : BaseIntEncodedValue(), MutableEncodedValue { +class MutableIntEncodedValue( + intEncodedValue: IntEncodedValue, +) : BaseIntEncodedValue(), + MutableEncodedValue { private var value = intEncodedValue.value fun setValue(value: Int) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt index 04953ff..b78e781 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseLongEncodedValue +import com.android.tools.smali.dexlib2.iface.value.LongEncodedValue -class MutableLongEncodedValue(longEncodedValue: LongEncodedValue) : BaseLongEncodedValue(), MutableEncodedValue { +class MutableLongEncodedValue( + longEncodedValue: LongEncodedValue, +) : BaseLongEncodedValue(), + MutableEncodedValue { private var value = longEncodedValue.value fun setValue(value: Long) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt similarity index 67% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt index b0aa267..0c19d0d 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt @@ -1,10 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.iface.value.MethodEncodedValue -class MutableMethodEncodedValue(methodEncodedValue: MethodEncodedValue) : - BaseMethodEncodedValue(), +class MutableMethodEncodedValue( + methodEncodedValue: MethodEncodedValue, +) : BaseMethodEncodedValue(), MutableEncodedValue { private var value = methodEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt similarity index 66% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt index 1899b3c..bbb2e51 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt @@ -1,10 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodHandleEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference +import com.android.tools.smali.dexlib2.iface.value.MethodHandleEncodedValue -class MutableMethodHandleEncodedValue(methodHandleEncodedValue: MethodHandleEncodedValue) : - BaseMethodHandleEncodedValue(), +class MutableMethodHandleEncodedValue( + methodHandleEncodedValue: MethodHandleEncodedValue, +) : BaseMethodHandleEncodedValue(), MutableEncodedValue { private var value = methodHandleEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt similarity index 63% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt index 57e1124..9538bb7 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt @@ -1,9 +1,13 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodTypeEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodProtoReference +import com.android.tools.smali.dexlib2.iface.value.MethodTypeEncodedValue -class MutableMethodTypeEncodedValue(methodTypeEncodedValue: MethodTypeEncodedValue) : BaseMethodTypeEncodedValue(), MutableEncodedValue { +class MutableMethodTypeEncodedValue( + methodTypeEncodedValue: MethodTypeEncodedValue, +) : BaseMethodTypeEncodedValue(), + MutableEncodedValue { private var value = methodTypeEncodedValue.value fun setValue(value: MethodProtoReference) { diff --git a/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt new file mode 100644 index 0000000..01f6383 --- /dev/null +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt @@ -0,0 +1,12 @@ +package app.revanced.com.android.tools.smali.dexlib2.iface.value + +import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue +import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue + +class MutableNullEncodedValue : + BaseNullEncodedValue(), + MutableEncodedValue { + companion object { + fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) + } +} diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt similarity index 62% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt index 740bcf7..6fecf17 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt @@ -1,9 +1,11 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseShortEncodedValue +import com.android.tools.smali.dexlib2.iface.value.ShortEncodedValue -class MutableShortEncodedValue(shortEncodedValue: ShortEncodedValue) : - BaseShortEncodedValue(), +class MutableShortEncodedValue( + shortEncodedValue: ShortEncodedValue, +) : BaseShortEncodedValue(), MutableEncodedValue { private var value = shortEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt similarity index 56% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt index 052e934..0ada57c 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt @@ -1,9 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseStringEncodedValue +import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue +import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue -class MutableStringEncodedValue(stringEncodedValue: StringEncodedValue) : - BaseStringEncodedValue(), +class MutableStringEncodedValue( + stringEncodedValue: StringEncodedValue, +) : BaseStringEncodedValue(), MutableEncodedValue { private var value = stringEncodedValue.value diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt similarity index 58% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt index ddf1436..597e4ca 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt @@ -1,8 +1,12 @@ -package com.android.tools.smali.dexlib2.iface.value +package app.revanced.com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseTypeEncodedValue +import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue -class MutableTypeEncodedValue(typeEncodedValue: TypeEncodedValue) : BaseTypeEncodedValue(), MutableEncodedValue { +class MutableTypeEncodedValue( + typeEncodedValue: TypeEncodedValue, +) : BaseTypeEncodedValue(), + MutableEncodedValue { private var value = typeEncodedValue.value fun setValue(value: String) { diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt similarity index 68% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt index 703d3cc..96ee279 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt @@ -1,10 +1,12 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable import com.android.tools.smali.dexlib2.base.BaseAnnotation import com.android.tools.smali.dexlib2.iface.Annotation -import com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable -class MutableAnnotation(annotation: Annotation) : BaseAnnotation() { +class MutableAnnotation( + annotation: Annotation, +) : BaseAnnotation() { private val visibility = annotation.visibility private val type = annotation.type private val _elements by lazy { annotation.elements.map { element -> element.toMutable() }.toMutableSet() } diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt similarity index 61% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt index 59076a7..b505c61 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt @@ -1,11 +1,13 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue +import app.revanced.com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable import com.android.tools.smali.dexlib2.base.BaseAnnotationElement import com.android.tools.smali.dexlib2.iface.AnnotationElement -import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue -import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable -class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnotationElement() { +class MutableAnnotationElement( + annotationElement: AnnotationElement, +) : BaseAnnotationElement() { private var name = annotationElement.name private var value = annotationElement.value.toMutable() diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt similarity index 84% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt index 77d5354..c2e8b59 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt @@ -1,14 +1,17 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference import com.android.tools.smali.dexlib2.iface.ClassDef -import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.util.FieldUtil import com.android.tools.smali.dexlib2.util.MethodUtil -class MutableClassDef(classDef: ClassDef) : BaseTypeReference(), ClassDef { +class MutableClassDef( + classDef: ClassDef, +) : BaseTypeReference(), + ClassDef { // Class private var type = classDef.type private var sourceFile = classDef.sourceFile diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableField.kt similarity index 77% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableField.kt index 6354912..f1144ee 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableField.kt @@ -1,12 +1,15 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue +import app.revanced.com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference import com.android.tools.smali.dexlib2.iface.Field -import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue -import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable -class MutableField(field: Field) : BaseFieldReference(), Field { +class MutableField( + field: Field, +) : BaseFieldReference(), + Field { private var definingClass = field.definingClass private var name = field.name private var type = field.type diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt similarity index 85% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt index a6dfdd6..b2278ef 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt @@ -1,12 +1,15 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethodParameter.Companion.toMutable import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableMethodParameter.Companion.toMutable -class MutableMethod(method: Method) : BaseMethodReference(), Method { +class MutableMethod( + method: Method, +) : BaseMethodReference(), + Method { private var definingClass = method.definingClass private var name = method.name private var accessFlags = method.accessFlags diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt similarity index 70% rename from patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt rename to patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt index 4540b1c..0d65e67 100644 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt @@ -1,10 +1,13 @@ -package com.android.tools.smali.dexlib2.mutable +package app.revanced.com.android.tools.smali.dexlib2.mutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable import com.android.tools.smali.dexlib2.base.BaseMethodParameter import com.android.tools.smali.dexlib2.iface.MethodParameter -import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable -class MutableMethodParameter(parameter: MethodParameter) : BaseMethodParameter(), MethodParameter { +class MutableMethodParameter( + parameter: MethodParameter, +) : BaseMethodParameter(), + MethodParameter { private var type = parameter.type private var name = parameter.name private var signature = parameter.signature diff --git a/patcher/src/commonMain/kotlin/app/revanced/java/io/File.kt b/patcher/src/commonMain/kotlin/app/revanced/java/io/File.kt new file mode 100644 index 0000000..a9cc0b4 --- /dev/null +++ b/patcher/src/commonMain/kotlin/app/revanced/java/io/File.kt @@ -0,0 +1,14 @@ +package app.revanced.java.io + +import java.io.BufferedWriter +import java.io.File +import java.io.FileInputStream +import java.nio.charset.Charset + +internal expect fun File.kmpResolve(child: String): File + +internal expect fun File.kmpDeleteRecursively(): Boolean + +internal expect fun File.kmpInputStream(): FileInputStream + +internal expect fun File.kmpBufferedWriter(charset: Charset): BufferedWriter diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/Matching.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/Matching.kt index 36cf6a6..276fb51 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/Matching.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/Matching.kt @@ -2,6 +2,7 @@ package app.revanced.patcher +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod import app.revanced.patcher.extensions.* import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags @@ -13,7 +14,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.* import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference -import com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.util.MethodUtil import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty @@ -131,8 +131,7 @@ fun Iterable.firstMutableMethodOrNull(methodReference: MethodReference) @JvmName("firstMutableMethodInMethods") context(_: BytecodePatchContext) -fun Iterable.firstMutableMethod(methodReference: MethodReference) = - requireNotNull(firstMutableMethodOrNull(methodReference)) +fun Iterable.firstMutableMethod(methodReference: MethodReference) = requireNotNull(firstMutableMethodOrNull(methodReference)) @JvmName("firstMethodOrNullInMethods") fun Iterable.firstMethodOrNull( @@ -210,8 +209,7 @@ fun Iterable.firstMethodOrNull(methodReference: MethodReference) = asSequence().flatMap { it.methods.asSequence() }.asIterable().firstMethodOrNull(methodReference) @JvmName("firstMethodInClassDefs") -fun Iterable.firstMethod(methodReference: MethodReference) = - requireNotNull(firstMethodOrNull(methodReference)) +fun Iterable.firstMethod(methodReference: MethodReference) = requireNotNull(firstMethodOrNull(methodReference)) @JvmName("firstMutableMethodOrNullInClassDefs") context(_: BytecodePatchContext) @@ -220,8 +218,7 @@ fun Iterable.firstMutableMethodOrNull(methodReference: MethodReference @JvmName("firstMutableMethodInClassDefs") context(_: BytecodePatchContext) -fun Iterable.firstMutableMethod(methodReference: MethodReference) = - requireNotNull(firstMutableMethodOrNull(methodReference)) +fun Iterable.firstMutableMethod(methodReference: MethodReference) = requireNotNull(firstMutableMethodOrNull(methodReference)) @JvmName("firstMethodOrNullInClassDefs") fun Iterable.firstMethodOrNull(predicate: MethodPredicate = { true }) = @@ -296,13 +293,11 @@ fun ClassDef.firstMethod(methodReference: MethodReference) = requireNotNull(firs @JvmName("firstMutableMethodOrNullInClassDef") context(_: BytecodePatchContext) -fun ClassDef.firstMutableMethodOrNull(methodReference: MethodReference) = - methods.firstMutableMethodOrNull(methodReference) +fun ClassDef.firstMutableMethodOrNull(methodReference: MethodReference) = methods.firstMutableMethodOrNull(methodReference) @JvmName("firstMutableMethodInClassDef") context(_: BytecodePatchContext) -fun ClassDef.firstMutableMethod(methodReference: MethodReference) = - requireNotNull(firstMutableMethodOrNull(methodReference)) +fun ClassDef.firstMutableMethod(methodReference: MethodReference) = requireNotNull(firstMutableMethodOrNull(methodReference)) @JvmName("firstMethodOrNullInClassDef") fun ClassDef.firstMethodOrNull( @@ -481,8 +476,7 @@ fun gettingFirstMethodOrNull(method: MethodReference) = cachedReadOnlyProperty { fun gettingFirstMethod(method: MethodReference) = cachedReadOnlyProperty { firstMethod(method) } -fun gettingFirstMutableMethodOrNull(method: MethodReference) = - cachedReadOnlyProperty { firstMutableMethodOrNull(method) } +fun gettingFirstMutableMethodOrNull(method: MethodReference) = cachedReadOnlyProperty { firstMutableMethodOrNull(method) } fun gettingFirstMutableMethod(method: MethodReference) = cachedReadOnlyProperty { firstMutableMethod(method) } @@ -959,9 +953,9 @@ fun MutablePredicateList.definingClass( fun MutablePredicateList.parameterTypes(vararg parameterTypePrefixes: String) = predicate { parameterTypes.size == parameterTypePrefixes.size && - parameterTypes - .zip(parameterTypePrefixes) - .all { (a, b) -> a.startsWith(b) } + parameterTypes + .zip(parameterTypePrefixes) + .all { (a, b) -> a.startsWith(b) } } fun MutablePredicateList.strings(build: Function>) { @@ -1039,8 +1033,7 @@ fun MutablePredicateList.opcodes(vararg opcodes: Opcode) = instructions inline fun `is`(crossinline predicate: Predicate = { true }): IndexedMatcherPredicate = { _, _, _ -> (this as? T)?.predicate() == true } -fun instruction(predicate: Predicate = { true }): IndexedMatcherPredicate = - { _, _, _ -> predicate() } +fun instruction(predicate: Predicate = { true }): IndexedMatcherPredicate = { _, _, _ -> predicate() } fun registers(predicate: Predicate = { true }): IndexedMatcherPredicate = { _, _, _ -> @@ -1084,8 +1077,7 @@ fun registers( }, ) = registers({ compare(registers) }) -fun literal(predicate: Predicate = { true }): IndexedMatcherPredicate = - { _, _, _ -> wideLiteral?.predicate() == true } +fun literal(predicate: Predicate = { true }): IndexedMatcherPredicate = { _, _, _ -> wideLiteral?.predicate() == true } fun literal( literal: Long, @@ -1112,8 +1104,7 @@ fun field( compare: String.(String) -> Boolean = String::equals, ) = field { this.name.compare(name) } -fun type(predicate: Predicate = { true }): IndexedMatcherPredicate = - { _, _, _ -> type?.predicate() == true } +fun type(predicate: Predicate = { true }): IndexedMatcherPredicate = { _, _, _ -> type?.predicate() == true } fun type( type: String, @@ -1158,13 +1149,13 @@ operator fun String.invoke(compare: String.(String) -> Boolean = String::equals) operator fun Opcode.invoke(): IndexedMatcherPredicate = { _, _, _ -> opcode == this@invoke } typealias BuildCompositeDeclarativePredicate = - context( + context( BytecodePatchContext, PredicateContext, IndexedMatcher, MutableList - ) - MutablePredicateList.() -> Unit + ) + MutablePredicateList.() -> Unit fun firstMethodComposite( vararg strings: String, diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/Patching.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/Patching.kt index eee24ae..f8194ae 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/Patching.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/Patching.kt @@ -1,10 +1,10 @@ package app.revanced.patcher +import app.revanced.java.io.kmpDeleteRecursively +import app.revanced.java.io.kmpResolve import app.revanced.patcher.patch.* import java.io.File import java.io.InputStream -import java.io.deleteRecursively -import java.io.resolve import java.util.logging.Logger fun patcher( @@ -19,20 +19,22 @@ fun patcher( if (temporaryFilesPath.exists()) { logger.info("Deleting existing temporary files directory") - if (!temporaryFilesPath.deleteRecursively()) + if (!temporaryFilesPath.kmpDeleteRecursively()) { logger.severe("Failed to delete existing temporary files directory") + } } - val apkFilesPath = temporaryFilesPath.resolve("apk").also { it.mkdirs() } - val patchedFilesPath = temporaryFilesPath.resolve("patched").also { it.mkdirs() } + val apkFilesPath = temporaryFilesPath.kmpResolve("apk").also { it.mkdirs() } + val patchedFilesPath = temporaryFilesPath.kmpResolve("patched").also { it.mkdirs() } - val resourcePatchContext = ResourcePatchContext( - apkFile, - apkFilesPath, - patchedFilesPath, - aaptBinaryPath, - frameworkFileDirectory - ) + val resourcePatchContext = + ResourcePatchContext( + apkFile, + apkFilesPath, + patchedFilesPath, + aaptBinaryPath, + frameworkFileDirectory, + ) val (packageName, versionName) = resourcePatchContext.decodeManifest() val patches = getPatches(packageName, versionName) @@ -41,10 +43,11 @@ fun patcher( if (patches.any { patch -> patch.patchesResources }) resourcePatchContext.decodeResources() // After initializing the resource context, to keep memory usage time low. - val bytecodePatchContext = BytecodePatchContext( - apkFile, - patchedFilesPath - ) + val bytecodePatchContext = + BytecodePatchContext( + apkFile, + patchedFilesPath, + ) logger.info("Warming up the cache") @@ -60,7 +63,7 @@ fun patcher( fun Set.apply( bytecodePatchContext: BytecodePatchContext, resourcePatchContext: ResourcePatchContext, - emit: (PatchResult) -> Unit + emit: (PatchResult) -> Unit, ): PatchesResult { val appliedPatches = LinkedHashMap() @@ -70,17 +73,23 @@ fun Set.apply( return if (result == null) { val failedDependency = dependencies.asSequence().map { it.apply() }.firstOrNull { it.exception != null } - if (failedDependency != null) return patchResult( - "The dependant patch \"$failedDependency\" of the patch \"$this\" raised an exception:\n" + + if (failedDependency != null) { + return patchResult( + "The dependant patch \"${failedDependency.patch}\" of the patch \"$this\" raised an exception:\n" + failedDependency.exception!!.stackTraceToString(), - ) + ) + } - val exception = runCatching { apply(bytecodePatchContext, resourcePatchContext) } - .exceptionOrNull() as? Exception + val exception = + runCatching { apply(bytecodePatchContext, resourcePatchContext) } + .exceptionOrNull() as? Exception patchResult(exception).also { result -> appliedPatches[this] = result } - } else if (result.exception == null) result - else patchResult("The patch '$this' has failed previously") + } else if (result.exception == null) { + result + } else { + patchResult("The patch '$this' has failed previously") + } } val patchResult = patch.apply() @@ -91,9 +100,10 @@ fun Set.apply( } } - val succeededPatchesWithFinalizeBlock = appliedPatches.values.filter { - it.exception == null && it.patch.afterDependents != null - } + val succeededPatchesWithFinalizeBlock = + appliedPatches.values.filter { + it.exception == null && it.patch.afterDependents != null + } succeededPatchesWithFinalizeBlock.asReversed().forEach { result -> val patch = result.patch @@ -107,9 +117,9 @@ fun Set.apply( "The patch \"$patch\" raised an exception:\n" + it.stackTraceToString(), it, ), - ) + ), ) - } + }, ) } @@ -126,14 +136,16 @@ class PatchesResult internal constructor( val dexFiles: Set, val resources: PatchedResources?, ) { - /** * A dex file. * * @param name The original name of the dex file. * @param stream The dex file as [InputStream]. */ - class PatchedDexFile internal constructor(val name: String, val stream: InputStream) + class PatchedDexFile internal constructor( + val name: String, + val stream: InputStream, + ) /** * The resources of a patched apk. diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt index 01160d1..6130370 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt @@ -1,5 +1,6 @@ package app.revanced.patcher.extensions +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcodes import com.android.tools.smali.dexlib2.builder.BuilderInstruction @@ -16,9 +17,7 @@ import org.antlr.runtime.TokenSource import org.antlr.runtime.tree.CommonTreeNodeStream import java.io.StringReader - -private inline fun Instruction.reference(): T? = - (this as? ReferenceInstruction)?.reference as? T +private inline fun Instruction.reference(): T? = (this as? ReferenceInstruction)?.reference as? T val Instruction.reference: Reference? get() = reference() @@ -64,7 +63,6 @@ val Instruction.string val Instruction.wideLiteral get() = (this as? NarrowLiteralInstruction)?.wideLiteral - private const val CLASS_HEADER = ".class LInlineCompiler;\n.super Ljava/lang/Object;\n" private const val STATIC_HEADER = "$CLASS_HEADER.method public static dummyMethod(" private const val HEADER = "$CLASS_HEADER.method public dummyMethod(" @@ -78,7 +76,7 @@ private val sb by lazy { StringBuilder(512) } * @param templateMethod The method to compile the instructions against. * @returns A list of instructions. */ -fun String.toInstructions(templateMethod: com.android.tools.smali.dexlib2.mutable.MutableMethod? = null): List { +fun String.toInstructions(templateMethod: MutableMethod? = null): List { val parameters = templateMethod?.parameterTypes?.joinToString("") { it } ?: "" val registers = templateMethod?.implementation?.registerCount ?: 1 // TODO: Should this be 0? val isStatic = templateMethod?.let { AccessFlags.STATIC.isSet(it.accessFlags) } ?: true @@ -99,17 +97,21 @@ fun String.toInstructions(templateMethod: com.android.tools.smali.dexlib2.mutabl if (lexer.numberOfSyntaxErrors > 0 || parser.numberOfSyntaxErrors > 0) { throw IllegalStateException( - "Lexer errors: ${lexer.numberOfSyntaxErrors}, Parser errors: ${parser.numberOfSyntaxErrors}" + "Lexer errors: ${lexer.numberOfSyntaxErrors}, Parser errors: ${parser.numberOfSyntaxErrors}", ) } - val treeStream = CommonTreeNodeStream(fileTree.tree).apply { - tokenStream = tokens - } + val treeStream = + CommonTreeNodeStream(fileTree.tree).apply { + tokenStream = tokens + } val walker = smaliTreeWalker(treeStream) walker.setDexBuilder(DexBuilder(Opcodes.getDefault())) val classDef = walker.smali_file() - return classDef.methods.first().instructions.map { it as BuilderInstruction } + return classDef.methods + .first() + .instructions + .map { it as BuilderInstruction } } diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt index 3b8f87c..23e9365 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt @@ -1,5 +1,6 @@ package app.revanced.patcher.extensions +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction @@ -9,10 +10,8 @@ import com.android.tools.smali.dexlib2.builder.instruction.* import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.MethodImplementation import com.android.tools.smali.dexlib2.iface.instruction.Instruction -import com.android.tools.smali.dexlib2.mutable.MutableMethod -fun Method.accessFlags(vararg flags: AccessFlags) = - accessFlags.and(flags.map { it.ordinal }.reduce { acc, i -> acc or i }) != 0 +fun Method.accessFlags(vararg flags: AccessFlags) = accessFlags.and(flags.map { it.ordinal }.reduce { acc, i -> acc or i }) != 0 /** * Add instructions to a method at the given index. @@ -31,8 +30,7 @@ fun MutableMethodImplementation.addInstructions( * * @param instructions The instructions to add. */ -fun MutableMethodImplementation.addInstructions(instructions: List) = - instructions.forEach { addInstruction(it) } +fun MutableMethodImplementation.addInstructions(instructions: List) = instructions.forEach { addInstruction(it) } /** * Remove instructions from a method at the given index. @@ -119,8 +117,7 @@ fun MutableMethod.addInstructions( * * @param instructions The instructions to add. */ -fun MutableMethod.addInstructions(instructions: List) = - implementation!!.addInstructions(instructions) +fun MutableMethod.addInstructions(instructions: List) = implementation!!.addInstructions(instructions) /** * Add instructions to a method. @@ -137,8 +134,7 @@ fun MutableMethod.addInstructions( * * @param smaliInstructions The instructions to add. */ -fun MutableMethod.addInstructions(smaliInstructions: String) = - implementation!!.addInstructions(smaliInstructions.toInstructions(this)) +fun MutableMethod.addInstructions(smaliInstructions: String) = implementation!!.addInstructions(smaliInstructions.toInstructions(this)) /** * Add instructions to a method at the given index. @@ -155,11 +151,12 @@ fun MutableMethod.addInstructionsWithLabels( ) { // Create reference dummy instructions for the instructions. val nopSmali = - StringBuilder(smaliInstructions).also { builder -> - externalLabels.forEach { (name, _) -> - builder.append("\n:$name\nnop") - } - }.toString() + StringBuilder(smaliInstructions) + .also { builder -> + externalLabels.forEach { (name, _) -> + builder.append("\n:$name\nnop") + } + }.toString() // Compile the instructions with the dummy labels val compiledInstructions = nopSmali.toInstructions(this) @@ -171,7 +168,9 @@ fun MutableMethod.addInstructionsWithLabels( ) implementation!!.apply { - this@apply.instructions.subList(index, index + compiledInstructions.size - externalLabels.size) + this@apply + .instructions + .subList(index, index + compiledInstructions.size - externalLabels.size) .forEachIndexed { compiledInstructionIndex, compiledInstruction -> // If the compiled instruction is not an offset instruction, skip it. if (compiledInstruction !is BuilderOffsetInstruction) return@forEachIndexed @@ -184,26 +183,43 @@ fun MutableMethod.addInstructionsWithLabels( fun replaceOffset( i: BuilderOffsetInstruction, label: Label, - ): BuilderOffsetInstruction { - return when (i) { - is BuilderInstruction10t -> BuilderInstruction10t(i.opcode, label) - is BuilderInstruction20t -> BuilderInstruction20t(i.opcode, label) - is BuilderInstruction21t -> BuilderInstruction21t(i.opcode, i.registerA, label) - is BuilderInstruction22t -> + ): BuilderOffsetInstruction = + when (i) { + is BuilderInstruction10t -> { + BuilderInstruction10t(i.opcode, label) + } + + is BuilderInstruction20t -> { + BuilderInstruction20t(i.opcode, label) + } + + is BuilderInstruction21t -> { + BuilderInstruction21t(i.opcode, i.registerA, label) + } + + is BuilderInstruction22t -> { BuilderInstruction22t( i.opcode, i.registerA, i.registerB, label, ) + } - is BuilderInstruction30t -> BuilderInstruction30t(i.opcode, label) - is BuilderInstruction31t -> BuilderInstruction31t(i.opcode, i.registerA, label) - else -> throw IllegalStateException( - "A non-offset instruction was given, this should never happen!", - ) + is BuilderInstruction30t -> { + BuilderInstruction30t(i.opcode, label) + } + + is BuilderInstruction31t -> { + BuilderInstruction31t(i.opcode, i.registerA, label) + } + + else -> { + throw IllegalStateException( + "A non-offset instruction was given, this should never happen!", + ) + } } - } // Create the final label. val label = newLabelForIndex(this@apply.instructions.indexOf(this)) @@ -443,4 +459,7 @@ fun MutableMethod.newLabel(index: Int) = implementation!!.newLabelForIndex(index * @param name The label name. * @param instruction The instruction that this label is for. */ -data class ExternalLabel(internal val name: String, internal val instruction: Instruction) +data class ExternalLabel( + internal val name: String, + internal val instruction: Instruction, +) diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt index 7ed366f..4c27d09 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt @@ -1,5 +1,10 @@ package app.revanced.patcher.patch +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableClassDef +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable +import app.revanced.java.io.kmpDeleteRecursively +import app.revanced.java.io.kmpInputStream +import app.revanced.java.io.kmpResolve import app.revanced.patcher.PatchesResult import app.revanced.patcher.extensions.instructionsOrNull import app.revanced.patcher.extensions.string @@ -9,13 +14,12 @@ import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.DexFile import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.mutable.MutableClassDef -import com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable import lanchon.multidexlib2.BasicDexFileNamer import lanchon.multidexlib2.DexIO import lanchon.multidexlib2.MultiDexIO import lanchon.multidexlib2.RawDexIO -import java.io.* +import java.io.File +import java.io.InputStream import java.util.logging.Logger import kotlin.reflect.jvm.jvmName @@ -34,9 +38,8 @@ class BytecodePatchContext internal constructor( inner class ClassDefs private constructor( dexFile: DexFile, - private val classDefs: MutableSet = dexFile.classes.toMutableSet() - ) : - MutableSet by classDefs { + private val classDefs: MutableSet = dexFile.classes.toMutableSet(), + ) : MutableSet by classDefs { private val byType = mutableMapOf() operator fun get(name: String): ClassDef? = byType[name] @@ -58,8 +61,8 @@ class BytecodePatchContext internal constructor( apkFile, BasicDexFileNamer(), null, - null - ) + null, + ), ) internal val opcodes = dexFile.opcodes @@ -113,8 +116,7 @@ class BytecodePatchContext internal constructor( return anyRemoved } - override fun retainAll(elements: Collection) = - removeAll(classDefs.asSequence().filter { it !in elements }) + override fun retainAll(elements: Collection) = removeAll(classDefs.asSequence().filter { it !in elements }) private fun addCache(classDef: ClassDef) { byType[classDef.type] = classDef @@ -131,15 +133,16 @@ class BytecodePatchContext internal constructor( byType -= classDef.type classDef.forEachString { method, string -> - if (_methodsByStrings[string]?.also { it -= method }?.isEmpty() == true) + if (_methodsByStrings[string]?.also { it -= method }?.isEmpty() == true) { _methodsByStrings -= string + } } } - private fun ClassDef.forEachString(action: (Method, String) -> Unit) { methods.asSequence().forEach { method -> - method.instructionsOrNull?.asSequence() + method.instructionsOrNull + ?.asSequence() ?.mapNotNull { it.string } ?.forEach { string -> action(method, string) } } @@ -184,16 +187,15 @@ class BytecodePatchContext internal constructor( * @param extensionInputStream The input stream for an extension dex file. */ internal fun extendWith(extensionInputStream: InputStream) { - RawDexIO.readRawDexFile( - extensionInputStream, 0, null - ).classes.forEach { classDef -> - val existingClass = classDefs[classDef.type] ?: run { - logger.fine { "Adding class \"$classDef\"" } + RawDexIO.readRawDexFile(extensionInputStream, 0, null).classes.forEach { classDef -> + val existingClass = + classDefs[classDef.type] ?: run { + logger.fine { "Adding class \"$classDef\"" } - classDefs += classDef + classDefs += classDef - return@forEach - } + return@forEach + } logger.fine { "Class \"$classDef\" exists already. Adding missing methods and fields." } @@ -232,32 +234,36 @@ class BytecodePatchContext internal constructor( System.gc() val patchedDexFileResults = - patchedFilesPath.resolve("dex").also { - it.deleteRecursively() // Make sure the directory is empty. - it.mkdirs() - }.apply { - MultiDexIO.writeDexFile( - true, - -1, - this, - BasicDexFileNamer(), - object : DexFile { - override fun getClasses() = classDefs.let { - // More performant according to - // https://github.com/LisoUseInAIKyrios/revanced-patcher/ - // commit/8c26ad08457fb1565ea5794b7930da42a1c81cf1 - // #diff-be698366d9868784ecf7da3fd4ac9d2b335b0bb637f9f618fbe067dbd6830b8fR197 - // TODO: Benchmark, if actually faster. - HashSet(it.size * 3 / 2).apply { addAll(it) } - } + patchedFilesPath + .kmpResolve("dex") + .also { + it.kmpDeleteRecursively() // Make sure the directory is empty. + it.mkdirs() + }.apply { + MultiDexIO.writeDexFile( + true, + -1, + this, + BasicDexFileNamer(), + object : DexFile { + override fun getClasses() = + classDefs.let { + // More performant according to + // https://github.com/LisoUseInAIKyrios/revanced-patcher/ + // commit/8c26ad08457fb1565ea5794b7930da42a1c81cf1 + // #diff-be698366d9868784ecf7da3fd4ac9d2b335b0bb637f9f618fbe067dbd6830b8fR197 + // TODO: Benchmark, if actually faster. + HashSet(it.size * 3 / 2).apply { addAll(it) } + } - override fun getOpcodes() = classDefs.opcodes - }, - DexIO.DEFAULT_MAX_DEX_POOL_SIZE, - ) { _, entryName, _ -> logger.info { "Compiled $entryName" } } - }.listFiles { it.isFile }!!.map { - PatchesResult.PatchedDexFile(it.name, it.inputStream()) - }.toSet() + override fun getOpcodes() = classDefs.opcodes + }, + DexIO.DEFAULT_MAX_DEX_POOL_SIZE, + ) { _, entryName, _ -> logger.info { "Compiled $entryName" } } + }.listFiles { it.isFile }!! + .map { + PatchesResult.PatchedDexFile(it.name, it.kmpInputStream()) + }.toSet() return patchedDexFileResults } diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt index 987bbc1..5515195 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt @@ -14,10 +14,12 @@ typealias PackageName = String typealias VersionName = String typealias Package = Pair?> -enum class PatchType(internal val prefix: String) { +enum class PatchType( + internal val prefix: String, +) { BYTECODE("Bytecode"), RAW_RESOURCE("RawResource"), - RESOURCE("Resource") + RESOURCE("Resource"), } internal val Patch.patchesResources: Boolean get() = type == PatchType.RESOURCE || dependencies.any { it.patchesResources } @@ -32,7 +34,10 @@ open class Patch internal constructor( internal val apply: context(BytecodePatchContext, ResourcePatchContext) () -> Unit, // Must be nullable, so that Patcher.invoke can check, // if a patch has an "afterDependents" in order to not emit it twice. - internal var afterDependents: (context(BytecodePatchContext, ResourcePatchContext) () -> Unit)?, + internal var afterDependents: ( + context(BytecodePatchContext, ResourcePatchContext) + () -> Unit + )?, internal val type: PatchType, ) { val options = Options(options) @@ -42,29 +47,30 @@ open class Patch internal constructor( sealed class PatchBuilder>( private val type: PatchType, - private val getPatchContext: context(BytecodePatchContext, ResourcePatchContext) () -> C ) { private var compatiblePackages: MutableSet? = null private val dependencies = mutableSetOf() private val options = mutableSetOf>() - internal var apply: context(BytecodePatchContext, ResourcePatchContext) () -> Unit = { } - internal var afterDependents: (context(BytecodePatchContext, ResourcePatchContext) () -> Unit)? = null + internal var apply: context(BytecodePatchContext, ResourcePatchContext) + () -> Unit = { } + internal var afterDependents: ( + context(BytecodePatchContext, ResourcePatchContext) + () -> Unit + )? = null context(_: BytecodePatchContext, _: ResourcePatchContext) - private val patchContext get() = getPatchContext() + abstract val context: C - fun apply(block: C.() -> Unit) { - apply = { block(patchContext) } + open fun apply(block: C.() -> Unit) { + apply = { block(context) } } fun afterDependents(block: C.() -> Unit) { - afterDependents = { block(patchContext) } + afterDependents = { block(context) } } - operator fun Option.invoke() = apply { - options += this - } + operator fun Option.invoke() = apply { options += this } operator fun String.invoke(vararg versions: VersionName) = invoke(versions.toSet()) @@ -84,8 +90,11 @@ sealed class PatchBuilder>( dependencies += patches } - - fun build(name: String?, description: String?, use: Boolean) = Patch( + fun build( + name: String?, + description: String?, + use: Boolean, + ) = Patch( name, description, use, @@ -98,33 +107,48 @@ sealed class PatchBuilder>( ) } +expect inline val currentClassLoader: ClassLoader + class BytecodePatchBuilder private constructor( - private var extensionInputStream: InputStream? = null -) : PatchBuilder( - PatchType.BYTECODE, - { - // Extend the context with the extension, before returning it to the patch before applying it. - contextOf().apply { - if (extensionInputStream != null) extendWith(extensionInputStream) - } - } -) { + @PublishedApi + internal var getExtensionInputStream: (() -> InputStream)? = null, +) : PatchBuilder(PatchType.BYTECODE) { internal constructor() : this(null) - fun extendWith(extension: String) { - // Should be the classloader which loaded the patch class. - val classLoader = Class.forName(Thread.currentThread().stackTrace[2].className).classLoader!! + // Must be inline to access the patch's classloader. + @Suppress("NOTHING_TO_INLINE") + inline fun extendWith(extension: String) { + // Should be the classloader which calls this function. + val classLoader = currentClassLoader - extensionInputStream = classLoader.getResourceAsStream(extension) - ?: throw PatchException("Extension \"$extension\" not found") + getExtensionInputStream = { + classLoader.getResourceAsStream(extension) + ?: throw PatchException("Extension \"$extension\" not found") + } + } + + context(_: BytecodePatchContext, _: ResourcePatchContext) + override val context get() = contextOf() + + override fun apply(block: BytecodePatchContext.() -> Unit) { + apply = { + block( + // Extend the context with the extension, before returning it to the patch before applying it. + context.apply { + getExtensionInputStream?.let { get -> extendWith(get()) } + }, + ) + } } } -open class ResourcePatchBuilder internal constructor(type: PatchType) : PatchBuilder( - type, - { contextOf() } -) { +open class ResourcePatchBuilder internal constructor( + type: PatchType, +) : PatchBuilder(type) { internal constructor() : this(PatchType.RESOURCE) + + context(_: BytecodePatchContext, _: ResourcePatchContext) + override val context get() = contextOf() } class RawResourcePatchBuilder internal constructor() : ResourcePatchBuilder() @@ -133,28 +157,28 @@ fun bytecodePatch( name: String? = null, description: String? = null, use: Boolean = true, - block: BytecodePatchBuilder.() -> Unit + block: BytecodePatchBuilder.() -> Unit, ) = BytecodePatchBuilder().apply(block).build(name, description, use) fun resourcePatch( name: String? = null, description: String? = null, use: Boolean = true, - block: ResourcePatchBuilder.() -> Unit + block: ResourcePatchBuilder.() -> Unit, ) = ResourcePatchBuilder().apply(block).build(name, description, use) fun rawResourcePatch( name: String? = null, description: String? = null, use: Boolean = true, - block: RawResourcePatchBuilder.() -> Unit + block: RawResourcePatchBuilder.() -> Unit, ) = RawResourcePatchBuilder().apply(block).build(name, description, use) private fun > creatingPatch( description: String? = null, use: Boolean = true, block: B.() -> Unit, - patchSupplier: (String?, String?, Boolean, B.() -> Unit) -> Patch + patchSupplier: (String?, String?, Boolean, B.() -> Unit) -> Patch, ) = ReadOnlyProperty { _, property -> patchSupplier(property.name, description, use, block) } fun creatingBytecodePatch( @@ -181,7 +205,6 @@ fun creatingRawResourcePatch( rawResourcePatch(name, description, use, block) } - /** * A common interface for contexts such as [ResourcePatchContext] and [BytecodePatchContext]. */ @@ -194,7 +217,10 @@ sealed interface PatchContext : Supplier * @param errorMessage The exception message. * @param cause The corresponding [Throwable]. */ -class PatchException(errorMessage: String?, cause: Throwable?) : Exception(errorMessage, cause) { +class PatchException( + errorMessage: String?, + cause: Throwable?, +) : Exception(errorMessage, cause) { constructor(errorMessage: String) : this(errorMessage, null) constructor(cause: Throwable) : this(cause.message, cause) } @@ -205,7 +231,10 @@ class PatchException(errorMessage: String?, cause: Throwable?) : Exception(error * @param patch The [Patch] that ran. * @param exception The [PatchException] thrown, if any. */ -class PatchResult internal constructor(val patch: Patch, val exception: PatchException? = null) +class PatchResult internal constructor( + val patch: Patch, + val exception: PatchException? = null, +) /** * Creates a [PatchResult] for this [Patch]. @@ -222,6 +251,7 @@ internal fun Patch.patchResult(exception: Exception? = null) = PatchResult(this, * @return The created [PatchResult]. */ internal fun Patch.patchResult(errorMessage: String) = PatchResult(this, PatchException(errorMessage)) + private fun Exception.toPatchException() = this as? PatchException ?: PatchException(this) /** @@ -229,22 +259,28 @@ private fun Exception.toPatchException() = this as? PatchException ?: PatchExcep * * @property patchesByFile The patches mapped by their patches file. */ -class Patches internal constructor(val patchesByFile: Map>) : Set -by patchesByFile.values.flatten().toSet() +class Patches internal constructor( + val patchesByFile: Map>, +) : Set + by patchesByFile.values.flatten().toSet() // Must be internal and a separate function for testing. @Suppress("MISSING_DEPENDENCY_IN_INFERRED_TYPE_ANNOTATION_WARNING") -internal fun getPatches(classNames: List, classLoader: ClassLoader): Set { - fun Member.isUsable() = - Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && (this !is Method || parameterCount == 0) +internal fun getPatches( + classNames: List, + classLoader: ClassLoader, +): Set { + fun Member.isUsable() = Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && (this !is Method || parameterCount == 0) - fun Class<*>.getPatchFields() = fields - .filter { it.type.isPatch && it.isUsable() } - .map { it.get(null) as Patch } + fun Class<*>.getPatchFields() = + fields + .filter { it.type.isPatch && it.isUsable() } + .map { it.get(null) as Patch } - fun Class<*>.getPatchMethods() = methods - .filter { it.returnType.isPatch && it.parameterCount == 0 && it.isUsable() } - .map { it.invoke(null) as Patch } + fun Class<*>.getPatchMethods() = + methods + .filter { it.returnType.isPatch && it.parameterCount == 0 && it.isUsable() } + .map { it.invoke(null) as Patch } return classNames .map { classLoader.loadClass(it) } @@ -257,13 +293,17 @@ internal fun loadPatches( vararg patchesFiles: File, getBinaryClassNames: (patchesFile: File) -> List, classLoader: ClassLoader, - onFailedToLoad: (File, Throwable) -> Unit -) = Patches(patchesFiles.map { file -> - file to getBinaryClassNames(file) -}.mapNotNull { (file, classNames) -> - runCatching { file to getPatches(classNames, classLoader) } - .onFailure { onFailedToLoad(file, it) }.getOrNull() -}.toMap()) + onFailedToLoad: (File, Throwable) -> Unit, +) = Patches( + patchesFiles + .map { file -> + file to getBinaryClassNames(file) + }.mapNotNull { (file, classNames) -> + runCatching { file to getPatches(classNames, classLoader) } + .onFailure { onFailedToLoad(file, it) } + .getOrNull() + }.toMap(), +) expect fun loadPatches( vararg patchesFiles: File, diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt index a39101f..78d272d 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt @@ -1,5 +1,6 @@ package app.revanced.patcher.patch +import app.revanced.java.io.kmpResolve import app.revanced.patcher.PatchesResult import app.revanced.patcher.util.Document import brut.androlib.AaptInvoker @@ -16,7 +17,6 @@ import brut.directory.ExtFile import java.io.File import java.io.InputStream import java.io.OutputStream -import java.io.resolve import java.nio.file.Files import java.util.logging.Logger import kotlin.reflect.jvm.jvmName @@ -41,10 +41,11 @@ class ResourcePatchContext internal constructor( private val logger = Logger.getLogger(ResourcePatchContext::class.jvmName) - private val resourceConfig = Config.getDefaultConfig().apply { - aaptBinary = aaptBinaryPath - frameworkDirectory = frameworkFileDirectory - } + private val resourceConfig = + Config.getDefaultConfig().apply { + aaptBinary = aaptBinaryPath + frameworkDirectory = frameworkFileDirectory + } internal var decodingMode = ResourceDecodingMode.MANIFEST @@ -105,18 +106,20 @@ class ResourcePatchContext internal constructor( internal fun decodeResources() { logger.info("Decoding resources") - val resourcesDecoder = ResourcesDecoder(resourceConfig, apkInfo).also { - it.decodeResources(apkFilesPath) - it.decodeManifest(apkFilesPath) - } + val resourcesDecoder = + ResourcesDecoder(resourceConfig, apkInfo).also { + it.decodeResources(apkFilesPath) + it.decodeManifest(apkFilesPath) + } // Record uncompressed files to preserve their state when recompiling. ApkDecoder(apkInfo, resourceConfig).recordUncompressedFiles(resourcesDecoder.resFileMapping) // Get the ids of the used framework packages to include them for reference when recompiling. - apkInfo.usesFramework = UsesFramework().apply { - ids = resourcesDecoder.resTable.listFramePackages().map { it.id } - } + apkInfo.usesFramework = + UsesFramework().apply { + ids = resourcesDecoder.resTable.listFramePackages().map { it.id } + } } /** @@ -127,51 +130,59 @@ class ResourcePatchContext internal constructor( override fun get(): PatchesResult.PatchedResources { logger.info("Compiling patched resources") - val resourcesPath = patchedFilesPath.resolve("resources").also { it.mkdirs() } + val resourcesPath = patchedFilesPath.kmpResolve("resources").also { it.mkdirs() } - val resourcesApkFile = if (decodingMode == ResourceDecodingMode.ALL) { - val resourcesApkFile = resourcesPath.resolve("resources.apk").also { it.createNewFile() } + val resourcesApkFile = + if (decodingMode == ResourceDecodingMode.ALL) { + val resourcesApkFile = resourcesPath.kmpResolve("resources.apk").also { it.createNewFile() } - val manifestFile = apkFilesPath.resolve("AndroidManifest.xml").also { - ResXmlUtils.fixingPublicAttrsInProviderAttributes(it) + val manifestFile = + apkFilesPath.kmpResolve("AndroidManifest.xml").also { + ResXmlUtils.fixingPublicAttrsInProviderAttributes(it) + } + val resPath = apkFilesPath.kmpResolve("res") + val frameworkApkFiles = + with(Framework(resourceConfig)) { + apkInfo.usesFramework.ids.map { id -> getFrameworkApk(id, null) } + }.toTypedArray() + + AaptInvoker( + resourceConfig, + apkInfo, + ).invoke(resourcesApkFile, manifestFile, resPath, null, null, frameworkApkFiles) + + resourcesApkFile + } else { + null } - val resPath = apkFilesPath.resolve("res") - val frameworkApkFiles = with(Framework(resourceConfig)) { - apkInfo.usesFramework.ids.map { id -> getFrameworkApk(id, null) } - }.toTypedArray() - AaptInvoker( - resourceConfig, - apkInfo - ).invoke(resourcesApkFile, manifestFile, resPath, null, null, frameworkApkFiles) - - resourcesApkFile - } else null - - - val otherFiles = apkFilesPath.listFiles()!!.filter { - // Excluded because present in resources.other. - // TODO: We are reusing apkFiles as a temporarily directory for extracting resources. - // This is not ideal as it could conflict with files such as the ones that are filtered here. - // The problem is that ResourcePatchContext#get returns a File relative to apkFiles, - // and we need to extract files to that directory. - // A solution would be to use apkFiles as the working directory for the patching process. - // Once all patches have been executed, we can move the decoded resources to a new directory. - // The filters wouldn't be needed anymore. - // For now, we assume that the files we filter here are not needed for the patching process. - it.name != "AndroidManifest.xml" && + val otherFiles = + apkFilesPath.listFiles()!!.filter { + // Excluded because present in resources.other. + // TODO: We are reusing apkFiles as a temporarily directory for extracting resources. + // This is not ideal as it could conflict with files such as the ones that are filtered here. + // The problem is that ResourcePatchContext#get returns a File relative to apkFiles, + // and we need to extract files to that directory. + // A solution would be to use apkFiles as the working directory for the patching process. + // Once all patches have been executed, we can move the decoded resources to a new directory. + // The filters wouldn't be needed anymore. + // For now, we assume that the files we filter here are not needed for the patching process. + it.name != "AndroidManifest.xml" && it.name != "res" && // Generated by Androlib. it.name != "build" - } - val otherResourceFiles = if (otherFiles.isNotEmpty()) { - // Move the other resources files. - resourcesPath.resolve("other").also { it.mkdirs() }.apply { - otherFiles.forEach { file -> - Files.move(file.toPath(), resolve(file.name).toPath()) - } } - } else null + val otherResourceFiles = + if (otherFiles.isNotEmpty()) { + // Move the other resources files. + resourcesPath.kmpResolve("other").also { it.mkdirs() }.apply { + otherFiles.forEach { file -> + Files.move(file.toPath(), resolve(file.name).toPath()) + } + } + } else { + null + } return PatchesResult.PatchedResources( resourcesApkFile, @@ -190,7 +201,7 @@ class ResourcePatchContext internal constructor( operator fun get( path: String, copy: Boolean = true, - ) = apkFilesPath.resolve(path).apply { + ) = apkFilesPath.kmpResolve(path).apply { if (copy && !exists()) { with(ExtFile(apkFile).directory) { if (containsFile(path) || containsDir(path)) { diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt index ade3f88..398e52d 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt @@ -1,11 +1,11 @@ package app.revanced.patcher.util -import com.android.tools.smali.dexlib2.mutable.MutableClassDef -import com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableField -import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableMethod -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableClassDef +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableField +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.util.ClassMerger.Utils.asMutableClass import app.revanced.patcher.util.ClassMerger.Utils.filterAny diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt index 1d5ea7c..9164b74 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt @@ -1,30 +1,30 @@ package app.revanced.patcher.util -import collections.merge +import app.revanced.collections.merge +import app.revanced.java.io.kmpBufferedWriter +import app.revanced.java.io.kmpInputStream import com.google.common.base.Charsets import org.w3c.dom.Document import java.io.Closeable import java.io.File import java.io.InputStream -import java.io.bufferedWriter -import java.io.inputStream import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult -import kotlin.use class Document internal constructor( inputStream: InputStream, -) : Document by DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream), Closeable { +) : Document by DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream), + Closeable { private var file: File? = null init { normalize() } - internal constructor(file: File) : this(file.inputStream()) { + internal constructor(file: File) : this(file.kmpInputStream()) { this.file = file readerCount.merge(file, 1, Int::plus) } @@ -34,7 +34,7 @@ class Document internal constructor( if (readerCount[it]!! > 1) { throw IllegalStateException( "Two or more instances are currently reading $it." + - "To be able to close this instance, no other instances may be reading $it at the same time.", + "To be able to close this instance, no other instances may be reading $it at the same time.", ) } else { readerCount.remove(it) @@ -45,7 +45,7 @@ class Document internal constructor( if (isAndroid) { transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-16") transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes") - val writer = it.bufferedWriter(charset = Charsets.UTF_8) + val writer = it.kmpBufferedWriter(charset = Charsets.UTF_8) transformer.transform(DOMSource(this), StreamResult(writer)) writer.close() } else { diff --git a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt index dbdd647..006cb5a 100644 --- a/patcher/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt +++ b/patcher/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt @@ -2,7 +2,7 @@ package app.revanced.patcher.util -import com.android.tools.smali.dexlib2.mutable.MutableMethod +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod import app.revanced.patcher.extensions.instructionsOrNull import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.iface.ClassDef @@ -30,9 +30,10 @@ class MethodNavigator internal constructor( context(_: BytecodePatchContext) private val lastNavigatedMethodInstructions - get() = with(original()) { - instructionsOrNull ?: throw NavigateException("Method $this does not have an implementation.") - } + get() = + with(original()) { + instructionsOrNull ?: throw NavigateException("Method $this does not have an implementation.") + } /** * Navigate to the method at the specified index. @@ -57,9 +58,16 @@ class MethodNavigator internal constructor( * @param predicate The predicate to match. */ context(_: BytecodePatchContext) - fun to(index: Int = 0, predicate: (Instruction) -> Boolean): MethodNavigator { - lastNavigatedMethodReference = lastNavigatedMethodInstructions.asSequence() - .filter(predicate).asIterable().getMethodReferenceAt(index) + fun to( + index: Int = 0, + predicate: (Instruction) -> Boolean, + ): MethodNavigator { + lastNavigatedMethodReference = + lastNavigatedMethodInstructions + .asSequence() + .filter(predicate) + .asIterable() + .getMethodReferenceAt(index) return this } @@ -70,8 +78,9 @@ class MethodNavigator internal constructor( * @param index The index of the method reference to get. */ private fun Iterable.getMethodReferenceAt(index: Int): MethodReference { - val instruction = elementAt(index) as? ReferenceInstruction - ?: throw NavigateException("Instruction at index $index is not a method reference.") + val instruction = + elementAt(index) as? ReferenceInstruction + ?: throw NavigateException("Instruction at index $index is not a method reference.") return instruction.reference as MethodReference } @@ -82,17 +91,19 @@ class MethodNavigator internal constructor( * @return The last navigated method mutably. */ context(context: BytecodePatchContext) - fun stop() = context.classDefs[lastNavigatedMethodReference.definingClass]!! - .firstMethodBySignature as MutableMethod - + fun stop() = + context.classDefs[lastNavigatedMethodReference.definingClass]!! + .firstMethodBySignature as MutableMethod /** * Get the last navigated method mutably. * * @return The last navigated method mutably. */ - operator fun getValue(context: BytecodePatchContext?, property: KProperty<*>) = - context(requireNotNull(context)) { stop() } + operator fun getValue( + context: BytecodePatchContext?, + property: KProperty<*>, + ) = context(requireNotNull(context)) { stop() } /** * Get the last navigated method immutably. @@ -106,14 +117,17 @@ class MethodNavigator internal constructor( * Find the first [lastNavigatedMethodReference] in the class. */ private val ClassDef.firstMethodBySignature - get() = methods.first { - MethodUtil.methodSignaturesMatch(it, lastNavigatedMethodReference) - } + get() = + methods.first { + MethodUtil.methodSignaturesMatch(it, lastNavigatedMethodReference) + } /** * An exception thrown when navigating fails. * * @param message The message of the exception. */ - internal class NavigateException internal constructor(message: String) : Exception(message) + internal class NavigateException internal constructor( + message: String, + ) : Exception(message) } diff --git a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt b/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt deleted file mode 100644 index e600c2a..0000000 --- a/patcher/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.android.tools.smali.dexlib2.iface.value - -import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue - -class MutableNullEncodedValue : BaseNullEncodedValue(), MutableEncodedValue { - companion object { - fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) - } -} diff --git a/patcher/src/commonMain/kotlin/java/io/File.kt b/patcher/src/commonMain/kotlin/java/io/File.kt deleted file mode 100644 index 8669495..0000000 --- a/patcher/src/commonMain/kotlin/java/io/File.kt +++ /dev/null @@ -1,17 +0,0 @@ -package java.io - -internal expect fun File.kmpResolve(child: String): File - -internal fun File.resolve(child: String) = kmpResolve(child) - -internal expect fun File.kmpDeleteRecursively(): Boolean - -internal fun File.deleteRecursively() = kmpDeleteRecursively() - -internal expect fun File.kmpInputStream(): InputStream - -internal fun File.inputStream() = kmpInputStream() - -internal expect fun File.kmpBufferedWriter(charset: java.nio.charset.Charset): BufferedWriter - -internal fun File.bufferedWriter(charset: java.nio.charset.Charset) = kmpBufferedWriter(charset) \ No newline at end of file diff --git a/patcher/src/jvmMain/kotlin/app/revanced/collections/MutableMap.jvm.kt b/patcher/src/jvmMain/kotlin/app/revanced/collections/MutableMap.jvm.kt new file mode 100644 index 0000000..d7fd58f --- /dev/null +++ b/patcher/src/jvmMain/kotlin/app/revanced/collections/MutableMap.jvm.kt @@ -0,0 +1,7 @@ +package app.revanced.collections + +internal actual fun MutableMap.kmpMerge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V, +) = MutableMap::merge.call(key, value, remappingFunction) as Unit diff --git a/patcher/src/jvmMain/kotlin/java/io/File.jvm.kt b/patcher/src/jvmMain/kotlin/app/revanced/java/io/File.jvm.kt similarity index 79% rename from patcher/src/jvmMain/kotlin/java/io/File.jvm.kt rename to patcher/src/jvmMain/kotlin/app/revanced/java/io/File.jvm.kt index 2772efc..69cf201 100644 --- a/patcher/src/jvmMain/kotlin/java/io/File.jvm.kt +++ b/patcher/src/jvmMain/kotlin/app/revanced/java/io/File.jvm.kt @@ -1,9 +1,12 @@ -package java.io +package app.revanced.java.io +import java.io.File import java.nio.charset.Charset - internal actual fun File.kmpResolve(child: String) = resolve(child) + internal actual fun File.kmpDeleteRecursively() = deleteRecursively() + internal actual fun File.kmpInputStream() = inputStream() -internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) \ No newline at end of file + +internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) diff --git a/patcher/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt b/patcher/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt index 947eb91..a4115bd 100644 --- a/patcher/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt +++ b/patcher/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt @@ -24,9 +24,14 @@ actual fun loadPatches( ) = loadPatches( patchesFiles = patchesFiles, { file -> - JarFile(file).entries().toList().filter { it.name.endsWith(".class") } + JarFile(file) + .entries() + .toList() + .filter { it.name.endsWith(".class") } .map { it.name.substringBeforeLast('.').replace('/', '.') } }, URLClassLoader(patchesFiles.map { it.toURI().toURL() }.toTypedArray()), - onFailedToLoad = onFailedToLoad + onFailedToLoad = onFailedToLoad, ) + +actual inline val currentClassLoader get() = object {}::class.java.classLoader diff --git a/patcher/src/jvmMain/kotlin/collections/MutableMap.jvm.kt b/patcher/src/jvmMain/kotlin/collections/MutableMap.jvm.kt deleted file mode 100644 index 4068c22..0000000 --- a/patcher/src/jvmMain/kotlin/collections/MutableMap.jvm.kt +++ /dev/null @@ -1,7 +0,0 @@ -package collections - -internal actual fun MutableMap.kmpMerge( - key: K, - value: V, - remappingFunction: (oldValue: V, newValue: V) -> V -) = merge(key, value, remappingFunction) \ No newline at end of file diff --git a/patcher/src/jvmTest/kotlin/app/revanced/patcher/MatchingTest.kt b/patcher/src/jvmTest/kotlin/app/revanced/patcher/MatchingTest.kt index 706d786..10763cc 100644 --- a/patcher/src/jvmTest/kotlin/app/revanced/patcher/MatchingTest.kt +++ b/patcher/src/jvmTest/kotlin/app/revanced/patcher/MatchingTest.kt @@ -21,42 +21,44 @@ class MatchingTest : PatcherTestBase() { @Test fun `finds via builder api`() { - fun firstMethodComposite(fail: Boolean = false) = firstMethodComposite { - name("method") - definingClass("class") + fun firstMethodComposite(fail: Boolean = false) = + firstMethodComposite { + name("method") + definingClass("class") - if (fail) returnType("doesnt exist") + if (fail) returnType("doesnt exist") - instructions( - at(0, Opcode.CONST_STRING()), - `is`(), - noneOf(registers()), - string("test", String::contains), - after(1..3, allOf(Opcode.INVOKE_VIRTUAL(), registers(1, 0))), - allOf(), - type("PrintStream;", String::endsWith) - ) - } + instructions( + at(0, Opcode.CONST_STRING()), + `is`(), + noneOf(registers()), + string("test", String::contains), + after(1..3, allOf(Opcode.INVOKE_VIRTUAL(), registers(1, 0))), + allOf(), + type("PrintStream;", String::endsWith), + ) + } with(bytecodePatchContext) { val match = firstMethodComposite() assertNotNull( match.methodOrNull, - "Expected to find a method" + "Expected to find a method", ) assertEquals( - 4, match.indices[3], - "Expected to find the string instruction at index 5" + 4, + match.indices[3], + "Expected to find the string instruction at index 4", ) assertNull( firstMethodComposite(fail = true).immutableMethodOrNull, - "Expected to not find a method" + "Expected to not find a method", ) assertNotNull( firstMethodComposite().match(classDefs.first()).methodOrNull, - "Expected to find a method matching in a specific class" + "Expected to find a method matching in a specific class", ) } } @@ -65,16 +67,17 @@ class MatchingTest : PatcherTestBase() { fun `finds via declarative api`() { bytecodePatch { apply { - val method = firstMethodDeclarativelyOrNull { - anyOf { - predicate { name == "method" } - add { false } + val method = + firstMethodDeclarativelyOrNull { + anyOf { + predicate { name == "method" } + add { false } + } + allOf { + predicate { returnType == "V" } + } + predicate { definingClass == "class" } } - allOf { - predicate { returnType == "V" } - } - predicate { definingClass == "class" } - } assertNotNull(method) { "Expected to find a method" } } }() @@ -99,7 +102,7 @@ class MatchingTest : PatcherTestBase() { } assertFalse( matcher(iterable), - "Should not match at any other index than first" + "Should not match at any other index than first", ) matcher.clear() @@ -107,7 +110,7 @@ class MatchingTest : PatcherTestBase() { assertEquals( listOf(0), matcher.indices, - "Should match at first index." + "Should match at first index.", ) matcher.clear() @@ -119,7 +122,7 @@ class MatchingTest : PatcherTestBase() { assertEquals( listOf(1), matcher.indices, - "Should find the index correctly." + "Should find the index correctly.", ) matcher.clear() @@ -131,7 +134,7 @@ class MatchingTest : PatcherTestBase() { assertEquals( listOf(0, 1, 3), matcher.indices, - "Should match 1, 2 and 4 at indices 0, 1 and 3." + "Should match 1, 2 and 4 at indices 0, 1 and 3.", ) matcher.clear() @@ -141,7 +144,7 @@ class MatchingTest : PatcherTestBase() { assertEquals( listOf(0), matcher.indices, - "Should match index 0 after nothing" + "Should match index 0 after nothing", ) matcher.clear() @@ -150,7 +153,7 @@ class MatchingTest : PatcherTestBase() { } assertFalse( matcher(iterable), - "Should not match, because 1 is out of range" + "Should not match, because 1 is out of range", ) matcher.clear() @@ -159,7 +162,7 @@ class MatchingTest : PatcherTestBase() { } assertFalse( matcher(iterable), - "Should not match, because 2 is at index 1" + "Should not match, because 2 is at index 1", ) matcher.clear() @@ -172,13 +175,18 @@ class MatchingTest : PatcherTestBase() { assertEquals( listOf(0, 3, 7, 8), matcher.indices, - "Should match indices correctly." + "Should match indices correctly.", ) } @Test fun `unordered matching works correctly`() { - val list = bytecodePatchContext.classDefs.first().methods.first().instructions + val list = + bytecodePatchContext.classDefs + .first() + .methods + .first() + .instructions val matcher = indexedMatcher() matcher.apply { @@ -187,13 +195,13 @@ class MatchingTest : PatcherTestBase() { afterAtLeast(1, Opcode.RETURN_OBJECT()), string(), Opcode.INVOKE_VIRTUAL(), - ) + ), ) }(list) assertEquals( listOf(4, 5, 6), matcher.indices, - "Should match because after(1) luckily only matches after the string at index 4." + "Should match because after(1) luckily only matches after the string at index 4.", ) matcher.clear() @@ -203,23 +211,25 @@ class MatchingTest : PatcherTestBase() { string("test", String::contains), string("Hello", String::contains), afterAtLeast(1, Opcode.RETURN_OBJECT()), - ) + ), ) }(list) assertEquals( listOf(0, 4, 5), matcher.indices, - "Should first match indices 4 due to the string, then after due to step 1, then the invoke." + "Should first match indices 4 due to the string, then after due to step 1, then the invoke.", ) assertFalse( indexedMatcher( - items = unorderedAllOf( - { _, _, _ -> this == 1 }, - { _, _, _ -> this == -1 }, - after(2) { this == -2 } - ))(listOf(1, -1, 1, 2, -2)), - "Should not match because because 1 is matched at index 0, too early for after(2)." + items = + unorderedAllOf( + { _, _, _ -> this == 1 }, + { _, _, _ -> this == -1 }, + after(2) { this == -2 }, + ), + )(listOf(1, -1, 1, 2, -2)), + "Should not match because because 1 is matched at index 0, too early for after(2).", ) } } diff --git a/patcher/src/jvmTest/kotlin/app/revanced/patcher/extensions/MethodExtensionsTest.kt b/patcher/src/jvmTest/kotlin/app/revanced/patcher/extensions/MethodExtensionsTest.kt index fdc524b..b2a2bfd 100644 --- a/patcher/src/jvmTest/kotlin/app/revanced/patcher/extensions/MethodExtensionsTest.kt +++ b/patcher/src/jvmTest/kotlin/app/revanced/patcher/extensions/MethodExtensionsTest.kt @@ -1,5 +1,7 @@ package app.revanced.patcher.extensions +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction @@ -7,24 +9,23 @@ import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21s import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.immutable.ImmutableMethod -import com.android.tools.smali.dexlib2.mutable.MutableMethod -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import org.junit.jupiter.api.BeforeEach import kotlin.test.Test import kotlin.test.assertEquals internal class MethodExtensionsTest { private val testInstructions = (0..9).map { i -> TestInstruction(i) } - private var method = ImmutableMethod( - "TestClass;", - "testMethod", - null, - "V", - AccessFlags.PUBLIC.value, - null, - null, - MutableMethodImplementation(16) - ).toMutable() + private var method = + ImmutableMethod( + "TestClass;", + "testMethod", + null, + "V", + AccessFlags.PUBLIC.value, + null, + null, + MutableMethodImplementation(16), + ).toMutable() @BeforeEach fun setup() { @@ -249,5 +250,7 @@ internal class MethodExtensionsTest { // endregion - private class TestInstruction(register: Int) : BuilderInstruction21s(Opcode.CONST_16, register, 0) + private class TestInstruction( + register: Int, + ) : BuilderInstruction21s(Opcode.CONST_16, register, 0) } diff --git a/patcher/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt b/patcher/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt index ffd2a86..225bfa9 100644 --- a/patcher/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt +++ b/patcher/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt @@ -1,29 +1,29 @@ package app.revanced.patcher.util +import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patcher.extensions.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t import com.android.tools.smali.dexlib2.immutable.ImmutableMethod -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import org.junit.jupiter.api.BeforeEach import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue internal class SmaliTest { - val method = ImmutableMethod( - "Ldummy;", - "name", - emptyList(), // parameters - "V", - AccessFlags.PUBLIC.value, - null, - null, - MutableMethodImplementation(1), - ).toMutable() - + val method = + ImmutableMethod( + "Ldummy;", + "name", + emptyList(), // parameters + "V", + AccessFlags.PUBLIC.value, + null, + null, + MutableMethodImplementation(1), + ).toMutable() @BeforeEach fun setup() { @@ -41,7 +41,10 @@ internal class SmaliTest { """, ) - val targetLocationIndex = method.getInstruction(1).target.location.index + val targetLocationIndex = + method + .getInstruction(1) + .target.location.index assertEquals(0, targetLocationIndex, "Label should point to index 0") } @@ -73,4 +76,4 @@ internal class SmaliTest { assertTrue(instruction.target.isPlaced, "Label should be placed") assertEquals(labelIndex, instruction.target.location.index) } -} \ No newline at end of file +}