diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt index e1f4803f9..413b40a8c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt @@ -184,7 +184,6 @@ val spoofBuildInfoPatch = bytecodePatch( type, user, ) - }, - - ) + } + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/extension/hooks/StartActivityInitHook.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/extension/hooks/StartActivityInitHook.kt index ee5905885..e3ea85bd5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/extension/hooks/StartActivityInitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/extension/hooks/StartActivityInitHook.kt @@ -1,5 +1,10 @@ package app.revanced.patches.googlenews.misc.extension.hooks +import app.revanced.patcher.definingClass +import app.revanced.patcher.extensions.instructions +import app.revanced.patcher.instructions +import app.revanced.patcher.invoke +import app.revanced.patcher.name import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow @@ -10,32 +15,30 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private var getApplicationContextIndex = -1 internal val startActivityInitHook = extensionHook( - getInsertIndex = { method -> - getApplicationContextIndex = method.indexOfFirstInstructionOrThrow { + getInsertIndex = { + getApplicationContextIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "getApplicationContext" } getApplicationContextIndex + 2 // Below the move-result-object instruction. }, - getContextRegister = { method -> - val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1) - as OneRegisterInstruction + getContextRegister = { + val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction "v${moveResultInstruction.registerA}" }, ) { - opcodes( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.IPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, // Calls startActivity.getApplicationContext(). - Opcode.MOVE_RESULT_OBJECT, + name("onCreate") + definingClass("/StartActivity;"::endsWith) + instructions( + Opcode.INVOKE_STATIC(), + Opcode.MOVE_RESULT(), + Opcode.CONST_4(), + Opcode.IF_EQZ(), + Opcode.CONST(), + Opcode.INVOKE_VIRTUAL(), + Opcode.IPUT_OBJECT(), + Opcode.IPUT_BOOLEAN(), + Opcode.INVOKE_VIRTUAL(), // Calls startActivity.getApplicationContext(). + Opcode.MOVE_RESULT_OBJECT(), ) - custom { methodDef, classDef -> - methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;") - } } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt index 6ddeb3e07..4a6701e7f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt @@ -1,9 +1,11 @@ package app.revanced.patches.googlenews.misc.gms -import app.revanced.patcher.fingerprint +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.definingClass +import app.revanced.patcher.name +import app.revanced.patcher.patch.BytecodePatchContext -internal val magazinesActivityOnCreateFingerprint = fingerprint { - custom { methodDef, classDef -> - methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;") - } +internal val BytecodePatchContext.magazinesActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass("/StartActivity;"::endsWith) } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt index 7a3982974..8eed5a896 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt @@ -11,7 +11,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = MAGAZINES_PACKAGE_NAME, toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME, - getMainActivityOnCreate = magazinesActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { magazinesActivityOnCreateMethod }, extensionPatch = extensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/extension/Hooks.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/extension/Hooks.kt index 085d6ce11..9fdbdea9a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/extension/Hooks.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/extension/Hooks.kt @@ -1,5 +1,10 @@ package app.revanced.patches.googlephotos.misc.extension +import app.revanced.patcher.definingClass +import app.revanced.patcher.extensions.instructions +import app.revanced.patcher.instructions +import app.revanced.patcher.invoke +import app.revanced.patcher.name import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow @@ -10,28 +15,26 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private var getApplicationContextIndex = -1 internal val homeActivityInitHook = extensionHook( - getInsertIndex = { method -> - getApplicationContextIndex = method.indexOfFirstInstructionOrThrow { + getInsertIndex = { + getApplicationContextIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "getApplicationContext" } getApplicationContextIndex + 2 // Below the move-result-object instruction. }, - getContextRegister = { method -> - val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1) - as OneRegisterInstruction + getContextRegister = { + val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction "v${moveResultInstruction.registerA}" }, ) { - opcodes( - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, // Calls getApplicationContext(). - Opcode.MOVE_RESULT_OBJECT, + name("onCreate") + definingClass("/HomeActivity;"::endsWith) + instructions( + Opcode.CONST_STRING(), + Opcode.INVOKE_STATIC(), + Opcode.MOVE_RESULT_OBJECT(), + Opcode.IF_NEZ(), + Opcode.INVOKE_VIRTUAL(), // Calls getApplicationContext(). + Opcode.MOVE_RESULT_OBJECT(), ) - custom { methodDef, classDef -> - methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;") - } } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt index f47c1a3d9..cda718393 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt @@ -1,9 +1,11 @@ package app.revanced.patches.googlephotos.misc.gms -import app.revanced.patcher.fingerprint +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.definingClass +import app.revanced.patcher.name +import app.revanced.patcher.patch.BytecodePatchContext -internal val homeActivityOnCreateFingerprint = fingerprint { - custom { methodDef, classDef -> - methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;") - } +internal val BytecodePatchContext.homeActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass("/HomeActivity;"::endsWith) } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt index f98bc0f01..1b2861572 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt @@ -10,7 +10,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = PHOTOS_PACKAGE_NAME, toPackageName = REVANCED_PHOTOS_PACKAGE_NAME, - getMainActivityOnCreate = homeActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { homeActivityOnCreateMethod }, extensionPatch = extensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt index cdf873624..aa00a581a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt @@ -18,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso ) }, - mainActivityFingerprint = mainActivityOnCreateMethod + getMainActivityMethod = { mainActivityOnCreateMethod } ) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/SharedExtensionPatch.kt index b10c321a4..1409c8f57 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/SharedExtensionPatch.kt @@ -6,5 +6,6 @@ import app.revanced.patches.shared.misc.extension.sharedExtensionPatch val sharedExtensionPatch = sharedExtensionPatch( "music", - applicationInitHook, applicationInitOnCreateHook + applicationInitHook, + applicationInitOnCreateHook ) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt index fde7053a4..d0c59cced 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt @@ -1,18 +1,15 @@ package app.revanced.patches.music.misc.extension.hooks +import app.revanced.patcher.* import app.revanced.patches.music.shared.YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook import app.revanced.patches.shared.misc.extension.extensionHook internal val applicationInitHook = extensionHook { - returns("V") - parameters() - instructions( - addString("activity") - ) - custom { method, _ -> method.name == "onCreate" } + name("onCreate") + returnType("V") + parameterTypes() + instructions("activity"()) } -internal val applicationInitOnCreateHook = activityOnCreateExtensionHook( - YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE -) +internal val applicationInitOnCreateHook = activityOnCreateExtensionHook(YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt index ce2b324ca..8db9d168c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt @@ -8,7 +8,7 @@ fun disableAdsPatch(block: BytecodePatchBuilder.() -> Unit = {}) = bytecodePatch name = "Disable ads", ) { apply { - isAdsEnabledFingerprint.method.returnEarly(false) + isAdsEnabledMethod.returnEarly(false) } block() diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt index e055493bd..8b9fd94d2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt @@ -1,10 +1,12 @@ package app.revanced.patches.reddit.customclients.sync.ads +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.accessFlags import com.android.tools.smali.dexlib2.AccessFlags -import app.revanced.patcher.fingerprint +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.returnType -internal val isAdsEnabledFingerprint = fingerprint { +internal val BytecodePatchContext.isAdsEnabledMethod by gettingFirstMutableMethodDeclaratively("SyncIapHelper") { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Z") - strings("SyncIapHelper") + returnType("Z") } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/BaseThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/BaseThemePatch.kt index fd7b38cc7..cd298fbb8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/BaseThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/BaseThemePatch.kt @@ -1,13 +1,8 @@ package app.revanced.patches.shared.layout.theme -import app.revanced.patcher.patch.BytecodePatchBuilder -import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch -import app.revanced.patcher.patch.stringOption +import app.revanced.patcher.patch.* import app.revanced.util.childElementsSequence -import java.util.Locale +import java.util.* internal const val THEME_COLOR_OPTION_DESCRIPTION = "Can be a hex color (#RRGGBB) or a color resource reference." @@ -56,7 +51,8 @@ internal fun validateColorName(colorString: String): Boolean { * Dark theme color option for YouTube and YT Music Theme patches. */ internal val darkThemeBackgroundColorOption = stringOption( - key = "darkThemeBackgroundColor", + name = "Dark theme background color", + description = THEME_COLOR_OPTION_DESCRIPTION, default = "@android:color/black", values = mapOf( "Pure black" to "@android:color/black", @@ -69,9 +65,7 @@ internal val darkThemeBackgroundColorOption = stringOption( "Dark yellow" to "#282900", "Dark orange" to "#291800", "Dark red" to "#290000", - ), - name = "Dark theme background color", - description = THEME_COLOR_OPTION_DESCRIPTION + ) ) /** @@ -104,10 +98,9 @@ internal fun baseThemeResourcePatch( lightColorNames: Set = THEME_DEFAULT_LIGHT_COLOR_NAMES, lightColorReplacement: (() -> String)? = null ) = resourcePatch { - apply { // After patch option validators are fixed https://github.com/ReVanced/revanced-patcher/issues/372 - // This should changed to a patch option validator. + // This should be changed to a patch option validator. val darkColor by darkThemeBackgroundColorOption if (!validateColorName(darkColor!!)) { throw PatchException("Invalid dark theme color: $darkColor") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch.kt index 845eb29f0..29aa14946 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch.kt @@ -1,17 +1,19 @@ package app.revanced.patches.shared.misc.checks import android.os.Build.* -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.all.misc.resources.addResources +import app.revanced.patches.all.misc.resources.addResourcesPatch import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue import com.android.tools.smali.dexlib2.iface.value.MutableLongEncodedValue import com.android.tools.smali.dexlib2.iface.value.MutableStringEncodedValue -import app.revanced.patches.all.misc.resources.addResources -import app.revanced.patches.all.misc.resources.addResourcesPatch import com.android.tools.smali.dexlib2.immutable.value.ImmutableLongEncodedValue import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue +import com.android.tools.smali.dexlib2.mutable.MutableClassDef +import com.android.tools.smali.dexlib2.mutable.MutableMethod import java.nio.charset.StandardCharsets import java.security.MessageDigest import kotlin.io.encoding.Base64 @@ -21,7 +23,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/checks/CheckEnvironmentPatch;" fun checkEnvironmentPatch( - mainActivityOnCreateFingerprint: Fingerprint, + getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod, extensionPatch: Patch, vararg compatiblePackages: String, ) = bytecodePatch( @@ -38,20 +40,20 @@ fun checkEnvironmentPatch( addResources("shared", "misc.checks.checkEnvironmentPatch") fun setPatchInfo() { - fun Fingerprint.setClassFields(vararg fieldNameValues: Pair) { + fun MutableClassDef.setClassFields(vararg fieldNameValues: Pair) { val fieldNameValueMap = mapOf(*fieldNameValues) - classDef.fields.forEach { field -> + fields.forEach { field -> field.initialValue = fieldNameValueMap[field.name] ?: return@forEach } } - patchInfoFingerprint.setClassFields( + patchInfoClassDef.setClassFields( "PATCH_TIME" to System.currentTimeMillis().encoded, ) fun setBuildInfo() { - patchInfoBuildFingerprint.setClassFields( + patchInfoBuildClassDef.setClassFields( "PATCH_BOARD" to BOARD.encodedAndHashed, "PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed, "PATCH_BRAND" to BRAND.encodedAndHashed, @@ -82,7 +84,7 @@ fun checkEnvironmentPatch( } } - fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstruction( + fun invokeCheck() = getMainActivityOnCreateMethod().addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt index 0eabd2f54..5ddaff0f2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.shared.misc.checks -import app.revanced.patcher.fingerprint +import app.revanced.patcher.BytecodePatchContextClassDefMatching.gettingFirstMutableClassDefDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext -internal val patchInfoFingerprint = fingerprint { - custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo;" } -} +internal val BytecodePatchContext.patchInfoClassDef by gettingFirstMutableClassDefDeclaratively( + "Lapp/revanced/extension/shared/checks/PatchInfo;" +) -internal val patchInfoBuildFingerprint = fingerprint { - custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo\$Build;" } -} +internal val BytecodePatchContext.patchInfoBuildClassDef by gettingFirstMutableClassDefDeclaratively( + $$"Lapp/revanced/extension/shared/checks/PatchInfo$Build;" +) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt index 3f567cca9..878fd40d4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt @@ -2,23 +2,16 @@ package app.revanced.patches.shared.misc.debugging import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.settings.preference.BasePreference -import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen -import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference -import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference +import app.revanced.patches.shared.misc.settings.preference.* import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting -import app.revanced.patches.shared.misc.settings.preference.SwitchPreference -import app.revanced.util.ResourceGroup -import app.revanced.util.copyResources -import app.revanced.util.findInstructionIndicesReversedOrThrow -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.* import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -45,7 +38,8 @@ internal fun enableDebuggingPatch( apply { copyResources( "settings", - ResourceGroup("drawable", + ResourceGroup( + "drawable", // Action buttons. "revanced_settings_copy_all.xml", "revanced_settings_deselect_all.xml", @@ -105,9 +99,7 @@ internal fun enableDebuggingPatch( ) // Hook the methods that look up if a feature flag is active. - experimentalBooleanFeatureFlagFingerprint.match( - experimentalFeatureFlagParentFingerprint.originalClassDef - ).method.apply { + experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalBooleanFeatureFlagMethod().apply { findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index -> val register = getInstruction(index).registerA @@ -121,15 +113,13 @@ internal fun enableDebuggingPatch( } } - experimentalDoubleFeatureFlagFingerprint.match( - experimentalFeatureFlagParentFingerprint.originalClassDef - ).method.apply { + experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalDoubleFeatureFlagMethod().apply { val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) addInstructions( insertIndex, """ - move-result-wide v0 # Also clobbers v1 (p0) since result is wide. + move-result-wide v0 # Also clobbers v1 (p0) since result is wide. invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isDoubleFeatureFlagEnabled(DJD)D move-result-wide v0 return-wide v0 @@ -137,9 +127,7 @@ internal fun enableDebuggingPatch( ) } - experimentalLongFeatureFlagFingerprint.match( - experimentalFeatureFlagParentFingerprint.originalClassDef - ).method.apply { + experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalLongFeatureFlagMethod().apply { val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) addInstructions( @@ -153,21 +141,20 @@ internal fun enableDebuggingPatch( ) } - if (hookStringFeatureFlag) experimentalStringFeatureFlagFingerprint.match( - experimentalFeatureFlagParentFingerprint.originalClassDef - ).method.apply { - val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT) + if (hookStringFeatureFlag) + experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalStringFeatureFlagMethod().apply { + val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT) - addInstructions( - insertIndex, - """ - move-result-object v0 - invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String; - move-result-object v0 - return-object v0 - """ - ) - } + addInstructions( + insertIndex, + """ + move-result-object v0 + invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String; + move-result-object v0 + return-object v0 + """ + ) + } // There exists other experimental accessor methods for byte[] // and wrappers for obfuscated classes, but currently none of those are hooked. diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/Fingerprints.kt index 6f183dd08..85bb9e4c5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/Fingerprints.kt @@ -1,35 +1,46 @@ package app.revanced.patches.shared.misc.debugging -import app.revanced.patcher.fingerprint +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMethodDeclaratively +import app.revanced.patcher.ClassDefMethodMatching.firstMutableMethodDeclaratively +import app.revanced.patcher.accessFlags +import app.revanced.patcher.parameterTypes +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val experimentalFeatureFlagParentFingerprint = fingerprint { +internal val BytecodePatchContext.experimentalFeatureFlagParentMethod by gettingFirstMethodDeclaratively( + "Unable to parse proto typed experiment flag: " +) { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("L") - parameters("L", "J", "[B") - strings("Unable to parse proto typed experiment flag: ") + returnType("L") + parameterTypes("L", "J", "[B") } -internal val experimentalBooleanFeatureFlagFingerprint = fingerprint { +context(_: BytecodePatchContext) +internal fun ClassDef.getExperimentalBooleanFeatureFlagMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Z") - parameters("L", "J", "Z") + returnType("Z") + parameterTypes("L", "J", "Z") } -internal val experimentalDoubleFeatureFlagFingerprint = fingerprint { +context(_: BytecodePatchContext) +internal fun ClassDef.getExperimentalDoubleFeatureFlagMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("D") - parameters("J", "D") + returnType("D") + parameterTypes("J", "D") } -internal val experimentalLongFeatureFlagFingerprint = fingerprint { +context(_: BytecodePatchContext) +internal fun ClassDef.getExperimentalLongFeatureFlagMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("J") - parameters("J", "J") + returnType("J") + parameterTypes("J", "J") } -internal val experimentalStringFeatureFlagFingerprint = fingerprint { +context(_: BytecodePatchContext) +internal fun ClassDef.getExperimentalStringFeatureFlagMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Ljava/lang/String;") - parameters("J", "Ljava/lang/String;") + returnType("Ljava/lang/String;") + parameterTypes("J", "Ljava/lang/String;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt index 28fae6bf0..29c93381a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt @@ -1,11 +1,11 @@ package app.revanced.patches.shared.misc.dns -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources +import com.android.tools.smali.dexlib2.mutable.MutableMethod private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/patches/CheckWatchHistoryDomainNameResolutionPatch;" @@ -16,7 +16,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = internal fun checkWatchHistoryDomainNameResolutionPatch( block: BytecodePatchBuilder.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {}, - mainActivityFingerprint: Fingerprint + getMainActivityMethod: BytecodePatchContext.() -> MutableMethod ) = bytecodePatch( name = "Check watch history domain name resolution", description = "Checks if the device DNS server is preventing user watch history from being saved.", @@ -28,7 +28,7 @@ internal fun checkWatchHistoryDomainNameResolutionPatch( addResources("shared", "misc.dns.checkWatchHistoryDomainNameResolutionPatch") - mainActivityFingerprint.method.addInstruction( + getMainActivityMethod().addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt index 626b2cf46..fbb7a20ff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt @@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.patch.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.all.misc.packagename.changePackageNamePatch import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.resources.addResources diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/check/CheckEnvironmentPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/check/CheckEnvironmentPatch.kt index 81d42ce66..d5321a855 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/check/CheckEnvironmentPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/check/CheckEnvironmentPatch.kt @@ -1,11 +1,11 @@ package app.revanced.patches.spotify.misc.check import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch -import app.revanced.patches.spotify.shared.mainActivityOnCreateFingerprint import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch +import app.revanced.patches.spotify.shared.mainActivityOnCreateMethod internal val checkEnvironmentPatch = checkEnvironmentPatch( - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { mainActivityOnCreateMethod }, extensionPatch = sharedExtensionPatch, "com.spotify.music", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt index d9b7bcdd8..2d7c820e9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt @@ -2,13 +2,13 @@ package app.revanced.patches.spotify.misc.extension import app.revanced.patcher.extensions.getInstruction import app.revanced.patches.shared.misc.extension.extensionHook -import app.revanced.patches.spotify.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.spotify.shared.mainActivityOnCreateMethod import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference -internal val mainActivityOnCreateHook = extensionHook { mainActivityOnCreateFingerprint } +internal val mainActivityOnCreateHook = extensionHook { mainActivityOnCreateMethod } internal val loadOrbitLibraryHook = extensionHook { // FIXME: Creating this is a mess and needs refactoring. diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt index 103f47750..4aec0b185 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt @@ -1,15 +1,21 @@ package app.revanced.patches.spotify.shared +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.accessFlags +import app.revanced.patcher.definingClass import app.revanced.patcher.fingerprint +import app.revanced.patcher.name +import app.revanced.patcher.parameterTypes +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivity;" -internal val mainActivityOnCreateFingerprint = fingerprint { +internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass(SPOTIFY_MAIN_ACTIVITY) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("V") - parameters("Landroid/os/Bundle;") - custom { method, classDef -> - method.name == "onCreate" && classDef.type == SPOTIFY_MAIN_ACTIVITY - } + returnType("V") + parameterTypes("Landroid/os/Bundle;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/extension/Hooks.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/extension/Hooks.kt index 794e522de..ed5f57046 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/extension/Hooks.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/extension/Hooks.kt @@ -1,5 +1,8 @@ package app.revanced.patches.tiktok.misc.extension +import app.revanced.patcher.definingClass +import app.revanced.patcher.name +import app.revanced.patcher.parameterTypes import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook import app.revanced.patches.shared.misc.extension.extensionHook @@ -16,19 +19,15 @@ internal val initHook = activityOnCreateExtensionHook( internal val jatoInitHook = extensionHook( getContextRegister = { "p1" } ) { - parameters("Landroid/content/Context;") - custom { method, classDef -> - classDef.type == "Lcom/ss/android/ugc/aweme/legoImp/task/JatoInitTask;" && - method.name == "run" - } + name("run") + definingClass("Lcom/ss/android/ugc/aweme/legoImp/task/JatoInitTask;") + parameterTypes("Landroid/content/Context;") } internal val storeRegionInitHook = extensionHook( getContextRegister = { "p1" } ) { - parameters("Landroid/content/Context;") - custom { method, classDef -> - classDef.type == "Lcom/ss/android/ugc/aweme/legoImp/task/StoreRegionInitTask;" && - method.name == "run" - } + name("run") + definingClass("Lcom/ss/android/ugc/aweme/legoImp/task/StoreRegionInitTask;") + parameterTypes("Landroid/content/Context;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt index a366929f9..837b12937 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt @@ -1,8 +1,8 @@ package app.revanced.patches.twitter.misc.hook import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.twitter.misc.hook.json.JsonHook import app.revanced.patches.twitter.misc.hook.json.addJsonHook +import app.revanced.patches.twitter.misc.hook.json.jsonHook import app.revanced.patches.twitter.misc.hook.json.jsonHookPatch fun hookPatch( @@ -19,6 +19,6 @@ fun hookPatch( ) apply { - addJsonHook(JsonHook(hookClassDescriptor)) + addJsonHook(jsonHook(hookClassDescriptor)) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt index 337aeb567..1c452a494 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt @@ -1,27 +1,29 @@ package app.revanced.patches.twitter.misc.hook.json -import app.revanced.patcher.fingerprint +import app.revanced.patcher.* +import app.revanced.patcher.BytecodePatchContextClassDefMatching.gettingFirstClassDef +import app.revanced.patcher.ClassDefMethodMatching.firstMutableMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val jsonHookPatchFingerprint = fingerprint { - opcodes( - Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list. +internal val jsonHookPatchMethodMatch = firstMethodComposite { + name("") + instructions( + Opcode.INVOKE_INTERFACE(), // Add dummy hook to hooks list. // Add hooks to the hooks list. - Opcode.INVOKE_STATIC, // Call buildList. + Opcode.INVOKE_STATIC(), // Call buildList. ) - custom { method, _ -> method.name == "" } } -internal val jsonInputStreamFingerprint = fingerprint { - custom { method, _ -> - if (method.parameterTypes.isEmpty()) { - false - } else { - method.parameterTypes.first() == "Ljava/io/InputStream;" - } +context(_: BytecodePatchContext) +internal fun ClassDef.getJsonInputStreamMethod() = firstMutableMethodDeclaratively { + custom { + if (parameterTypes.isEmpty()) false + else parameterTypes.first() == "Ljava/io/InputStream;" } } -internal val loganSquareFingerprint = fingerprint { - custom { _, classDef -> classDef.endsWith("LoganSquare;") } +internal val BytecodePatchContext.loganSquareClassDef by gettingFirstClassDef { + type.endsWith("LoganSquare;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt index 66ab1997b..41962f155 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt @@ -1,8 +1,8 @@ package app.revanced.patches.twitter.misc.hook.json +import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstClassDef import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.removeInstructions -import app.revanced.patcher.firstClassDef import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch @@ -15,24 +15,21 @@ import java.io.InvalidClassException * * @param jsonHook The [JsonHook] to add. */ -context(BytecodePatchContext) -fun addJsonHook( +fun BytecodePatchContext.addJsonHook( jsonHook: JsonHook, ) { if (jsonHook.added) return - jsonHookPatchFingerprint.method.apply { - // Insert hooks right before calling buildList. - val insertIndex = jsonHookPatchFingerprint.instructionMatches.last().index + // Insert hooks right before calling buildList. + val insertIndex = jsonHookPatchMethodMatch.indices.last() - addInstructions( - insertIndex, - """ - sget-object v1, ${jsonHook.descriptor}->INSTANCE:${jsonHook.descriptor} - invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z - """, - ) - } + jsonHookPatchMethodMatch.method.addInstructions( + insertIndex, + """ + sget-object v1, ${jsonHook.descriptor}->INSTANCE:${jsonHook.descriptor} + invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z + """, + ) jsonHook.added = true } @@ -48,15 +45,13 @@ val jsonHookPatch = bytecodePatch( dependsOn(sharedExtensionPatch) apply { - jsonHookPatchFingerprint.apply { - val jsonHookPatch = firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR) - - matchOrNull(jsonHookPatch) + jsonHookPatchMethodMatch.apply { + match(firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR)).methodOrNull ?: throw PatchException("Unexpected extension.") } val jsonFactoryClassDef = - loganSquareFingerprint.originalClassDef // Conveniently find the type to hook a method in, via a named field. + loganSquareClassDef // Conveniently find the type to hook a method in, via a named field. .fields .firstOrNull { it.name == "JSON_FACTORY" } ?.type @@ -64,7 +59,7 @@ val jsonHookPatch = bytecodePatch( ?: throw PatchException("Could not find required class.") // Hook the methods first parameter. - jsonInputStreamFingerprint.match(jsonFactoryClassDef).method.addInstructions( + jsonFactoryClassDef.getJsonInputStreamMethod().addInstructions( 0, """ invoke-static { p1 }, $JSON_HOOK_PATCH_CLASS_DESCRIPTOR->parseJsonHook(Ljava/io/InputStream;)Ljava/io/InputStream; @@ -75,14 +70,19 @@ val jsonHookPatch = bytecodePatch( afterDependents { // Remove hooks.add(dummyHook). - jsonHookPatchFingerprint.method.apply { - val addDummyHookIndex = jsonHookPatchFingerprint.instructionMatches.last().index - 2 + val addDummyHookIndex = jsonHookPatchMethodMatch.indices.last() - removeInstructions(addDummyHookIndex, 2) - } + jsonHookPatchMethodMatch.method.removeInstructions(addDummyHookIndex, 2) } } + +class JsonHook internal constructor( + internal val descriptor: String, +) { + internal var added = false +} + /** * Create a hook class. * The class has to extend on **JsonHook**. @@ -91,22 +91,18 @@ val jsonHookPatch = bytecodePatch( * @param descriptor The class descriptor of the hook. * @throws ClassNotFoundException If the class could not be found. */ -context(BytecodePatchContext) -class JsonHook( - internal val descriptor: String, -) { - internal var added = false - - init { - firstClassDef(descriptor).let { - it.also { classDef -> - if ( - classDef.superclass != JSON_HOOK_CLASS_DESCRIPTOR || - !classDef.fields.any { field -> field.name == "INSTANCE" } - ) { - throw InvalidClassException(classDef.type, "Not a hook class") - } +context(_: BytecodePatchContext) +fun jsonHook(descriptor: String): JsonHook { + firstClassDef(descriptor).let { + it.also { classDef -> + if ( + classDef.superclass != JSON_HOOK_CLASS_DESCRIPTOR || + !classDef.fields.any { field -> field.name == "INSTANCE" } + ) { + throw InvalidClassException(classDef.type, "Not a hook class") } } } -} + + return JsonHook(JSON_HOOK_CLASS_DESCRIPTOR) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt index 75d7aead3..9c7becb37 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt @@ -16,7 +16,7 @@ import app.revanced.patches.youtube.misc.playercontrols.injectVisibilityCheckCal import app.revanced.patches.youtube.misc.playercontrols.playerControlsPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.util.ResourceGroup import app.revanced.util.copyResources @@ -85,7 +85,7 @@ val downloadsPatch = bytecodePatch( injectVisibilityCheckCall(BUTTON_DESCRIPTOR) // Main activity is used to launch downloader intent. - mainActivityOnCreateFingerprint.method.addInstruction( + mainActivityOnCreateMethod.method.addInstruction( 0, "invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->setMainActivity(Landroid/app/Activity;)V" ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt index cf21471fa..eef223b73 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt @@ -5,7 +5,6 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_MAIN_ACTIVITY_NAME import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME import app.revanced.patches.youtube.misc.settings.PreferenceScreen -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint @Suppress("unused") val customBrandingPatch = baseCustomBrandingPatch( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt index 6c4543ade..69ad11ad0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt @@ -14,10 +14,9 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_30_or_greater import app.revanced.patches.youtube.misc.playservice.is_20_34_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.getReference import app.revanced.util.insertLiteralOverride @@ -155,7 +154,7 @@ val seekbarColorPatch = bytecodePatch( } // Hook the splash animation to set the a seekbar color. - mainActivityOnCreateFingerprint.method.apply { + mainActivityOnCreateMethod.method.apply { val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt index 3508d7e1a..0c4c486cb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt @@ -15,7 +15,7 @@ import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow @@ -65,7 +65,7 @@ val shortsAutoplayPatch = bytecodePatch( } // Main activity is used to check if app is in pip mode. - mainActivityOnCreateFingerprint.method.addInstruction( + mainActivityOnCreateMethod.method.addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt index e9b21bdca..378f605c5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.playservice.is_20_39_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod import app.revanced.util.findFreeRegister import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow @@ -61,7 +61,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch( ) // Activity is used as the context to launch an Intent. - mainActivityOnCreateFingerprint.method.addInstruction( + mainActivityOnCreateMethod.method.addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" + "setMainActivity(Landroid/app/Activity;)V", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt index cd00c6295..fe462f712 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/announcements/AnnouncementsPatch;" @@ -37,7 +37,7 @@ val announcementsPatch = bytecodePatch( SwitchPreference("revanced_announcements"), ) - mainActivityOnCreateFingerprint.method.addInstruction( + mainActivityOnCreateMethod.method.addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch.kt index 9624721bb..ffb245123 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch.kt @@ -2,10 +2,10 @@ package app.revanced.patches.youtube.misc.check import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod internal val checkEnvironmentPatch = checkEnvironmentPatch( - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { mainActivityOnCreateMethod }, extensionPatch = sharedExtensionPatch, "com.google.android.youtube", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt index b0898cdc5..1a0da97e2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt @@ -2,7 +2,6 @@ package app.revanced.patches.youtube.misc.dns import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch( block = { @@ -19,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso ) ) }, - mainActivityFingerprint = mainActivityOnCreateFingerprint + getMainActivityMethod = mainActivityOnCreateFingerprint ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt index 6807f51cd..66bd72947 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt @@ -13,7 +13,6 @@ import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.spoof.spoofVideoStreamsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint @Suppress("unused") val gmsCoreSupportPatch = gmsCoreSupportPatch( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt index 32824fcb8..ffe6d364f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt @@ -13,7 +13,6 @@ import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint val spoofVideoStreamsPatch = spoofVideoStreamsPatch( extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index c2d2aabcf..833b0db2d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -1,5 +1,7 @@ package app.revanced.patches.youtube.shared +import app.revanced.patcher.BytecodePatchContextMethodMatching.firstMutableMethodDeclaratively +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively import app.revanced.patcher.InstructionLocation.MatchAfterImmediately import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint @@ -8,6 +10,11 @@ import app.revanced.patcher.methodCall import app.revanced.patcher.newInstance import app.revanced.patcher.opcode import app.revanced.patcher.addString +import app.revanced.patcher.definingClass +import app.revanced.patcher.name +import app.revanced.patcher.parameterTypes +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.returnType import app.revanced.patches.shared.misc.mapping.ResourceType import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags @@ -58,12 +65,11 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint { } } -internal val mainActivityOnCreateFingerprint = fingerprint { - returns("V") - parameters("Landroid/os/Bundle;") - custom { method, classDef -> - method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE - } +internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE) + returnType("V") + parameterTypes("Landroid/os/Bundle;") } internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint { @@ -87,8 +93,8 @@ internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint { ) custom { _, classDef -> classDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;" || - classDef.superclass == - "Lcom/google/android/libraries/youtube/rendering/ui/spec/typography/YouTubeAppCompatTextView;" + classDef.superclass == + "Lcom/google/android/libraries/youtube/rendering/ui/spec/typography/YouTubeAppCompatTextView;" } } @@ -128,6 +134,10 @@ internal val videoQualityChangedFingerprint = fingerprint { newInstance("Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"), opcode(Opcode.IGET_OBJECT), opcode(Opcode.CHECK_CAST), - fieldAccess(type = "I", opcode = Opcode.IGET, location = MatchAfterImmediately()), // Video resolution (human readable). + fieldAccess( + type = "I", + opcode = Opcode.IGET, + location = MatchAfterImmediately() + ), // Video resolution (human readable). ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt index 37fe186ac..888dbb7e5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt @@ -6,7 +6,6 @@ import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint @Suppress("unused") val forceOriginalAudioPatch = forceOriginalAudioPatch(