finish batch1

This commit is contained in:
oSumAtrIX 2026-01-11 03:09:35 +01:00
parent a103eb5b7a
commit 32dfe48ad7
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
38 changed files with 265 additions and 254 deletions

View file

@ -184,7 +184,6 @@ val spoofBuildInfoPatch = bytecodePatch(
type, type,
user, user,
) )
}, }
)
)
} }

View file

@ -1,5 +1,10 @@
package app.revanced.patches.googlenews.misc.extension.hooks 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.patches.shared.misc.extension.extensionHook
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@ -10,32 +15,30 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private var getApplicationContextIndex = -1 private var getApplicationContextIndex = -1
internal val startActivityInitHook = extensionHook( internal val startActivityInitHook = extensionHook(
getInsertIndex = { method -> getInsertIndex = {
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow { getApplicationContextIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "getApplicationContext" getReference<MethodReference>()?.name == "getApplicationContext"
} }
getApplicationContextIndex + 2 // Below the move-result-object instruction. getApplicationContextIndex + 2 // Below the move-result-object instruction.
}, },
getContextRegister = { method -> getContextRegister = {
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1) val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction
as OneRegisterInstruction
"v${moveResultInstruction.registerA}" "v${moveResultInstruction.registerA}"
}, },
) { ) {
opcodes( name("onCreate")
Opcode.INVOKE_STATIC, definingClass("/StartActivity;"::endsWith)
Opcode.MOVE_RESULT, instructions(
Opcode.CONST_4, Opcode.INVOKE_STATIC(),
Opcode.IF_EQZ, Opcode.MOVE_RESULT(),
Opcode.CONST, Opcode.CONST_4(),
Opcode.INVOKE_VIRTUAL, Opcode.IF_EQZ(),
Opcode.IPUT_OBJECT, Opcode.CONST(),
Opcode.IPUT_BOOLEAN, Opcode.INVOKE_VIRTUAL(),
Opcode.INVOKE_VIRTUAL, // Calls startActivity.getApplicationContext(). Opcode.IPUT_OBJECT(),
Opcode.MOVE_RESULT_OBJECT, Opcode.IPUT_BOOLEAN(),
Opcode.INVOKE_VIRTUAL(), // Calls startActivity.getApplicationContext().
Opcode.MOVE_RESULT_OBJECT(),
) )
custom { methodDef, classDef ->
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;")
}
} }

View file

@ -1,9 +1,11 @@
package app.revanced.patches.googlenews.misc.gms 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 { internal val BytecodePatchContext.magazinesActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
custom { methodDef, classDef -> name("onCreate")
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;") definingClass("/StartActivity;"::endsWith)
}
} }

View file

@ -11,7 +11,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = MAGAZINES_PACKAGE_NAME, fromPackageName = MAGAZINES_PACKAGE_NAME,
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME, toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
getMainActivityOnCreate = magazinesActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { magazinesActivityOnCreateMethod },
extensionPatch = extensionPatch, extensionPatch = extensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {

View file

@ -1,5 +1,10 @@
package app.revanced.patches.googlephotos.misc.extension 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.patches.shared.misc.extension.extensionHook
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@ -10,28 +15,26 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private var getApplicationContextIndex = -1 private var getApplicationContextIndex = -1
internal val homeActivityInitHook = extensionHook( internal val homeActivityInitHook = extensionHook(
getInsertIndex = { method -> getInsertIndex = {
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow { getApplicationContextIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "getApplicationContext" getReference<MethodReference>()?.name == "getApplicationContext"
} }
getApplicationContextIndex + 2 // Below the move-result-object instruction. getApplicationContextIndex + 2 // Below the move-result-object instruction.
}, },
getContextRegister = { method -> getContextRegister = {
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1) val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction
as OneRegisterInstruction
"v${moveResultInstruction.registerA}" "v${moveResultInstruction.registerA}"
}, },
) { ) {
opcodes( name("onCreate")
Opcode.CONST_STRING, definingClass("/HomeActivity;"::endsWith)
Opcode.INVOKE_STATIC, instructions(
Opcode.MOVE_RESULT_OBJECT, Opcode.CONST_STRING(),
Opcode.IF_NEZ, Opcode.INVOKE_STATIC(),
Opcode.INVOKE_VIRTUAL, // Calls getApplicationContext(). Opcode.MOVE_RESULT_OBJECT(),
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;")
}
} }

View file

@ -1,9 +1,11 @@
package app.revanced.patches.googlephotos.misc.gms 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 { internal val BytecodePatchContext.homeActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
custom { methodDef, classDef -> name("onCreate")
methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;") definingClass("/HomeActivity;"::endsWith)
}
} }

View file

@ -10,7 +10,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = PHOTOS_PACKAGE_NAME, fromPackageName = PHOTOS_PACKAGE_NAME,
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME, toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
getMainActivityOnCreate = homeActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { homeActivityOnCreateMethod },
extensionPatch = extensionPatch, extensionPatch = extensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {

View file

@ -18,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso
) )
}, },
mainActivityFingerprint = mainActivityOnCreateMethod getMainActivityMethod = { mainActivityOnCreateMethod }
) )

View file

@ -6,5 +6,6 @@ import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch( val sharedExtensionPatch = sharedExtensionPatch(
"music", "music",
applicationInitHook, applicationInitOnCreateHook applicationInitHook,
applicationInitOnCreateHook
) )

View file

@ -1,18 +1,15 @@
package app.revanced.patches.music.misc.extension.hooks 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.music.shared.YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook
import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.patches.shared.misc.extension.extensionHook
internal val applicationInitHook = extensionHook { internal val applicationInitHook = extensionHook {
returns("V") name("onCreate")
parameters() returnType("V")
instructions( parameterTypes()
addString("activity") instructions("activity"())
)
custom { method, _ -> method.name == "onCreate" }
} }
internal val applicationInitOnCreateHook = activityOnCreateExtensionHook( internal val applicationInitOnCreateHook = activityOnCreateExtensionHook(YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE)
YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
)

View file

@ -8,7 +8,7 @@ fun disableAdsPatch(block: BytecodePatchBuilder.() -> Unit = {}) = bytecodePatch
name = "Disable ads", name = "Disable ads",
) { ) {
apply { apply {
isAdsEnabledFingerprint.method.returnEarly(false) isAdsEnabledMethod.returnEarly(false)
} }
block() block()

View file

@ -1,10 +1,12 @@
package app.revanced.patches.reddit.customclients.sync.ads 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 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) accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Z") returnType("Z")
strings("SyncIapHelper")
} }

View file

@ -1,13 +1,8 @@
package app.revanced.patches.shared.layout.theme package app.revanced.patches.shared.layout.theme
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.*
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.util.childElementsSequence 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." 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. * Dark theme color option for YouTube and YT Music Theme patches.
*/ */
internal val darkThemeBackgroundColorOption = stringOption( internal val darkThemeBackgroundColorOption = stringOption(
key = "darkThemeBackgroundColor", name = "Dark theme background color",
description = THEME_COLOR_OPTION_DESCRIPTION,
default = "@android:color/black", default = "@android:color/black",
values = mapOf( values = mapOf(
"Pure black" to "@android:color/black", "Pure black" to "@android:color/black",
@ -69,9 +65,7 @@ internal val darkThemeBackgroundColorOption = stringOption(
"Dark yellow" to "#282900", "Dark yellow" to "#282900",
"Dark orange" to "#291800", "Dark orange" to "#291800",
"Dark red" to "#290000", "Dark red" to "#290000",
), )
name = "Dark theme background color",
description = THEME_COLOR_OPTION_DESCRIPTION
) )
/** /**
@ -104,10 +98,9 @@ internal fun baseThemeResourcePatch(
lightColorNames: Set<String> = THEME_DEFAULT_LIGHT_COLOR_NAMES, lightColorNames: Set<String> = THEME_DEFAULT_LIGHT_COLOR_NAMES,
lightColorReplacement: (() -> String)? = null lightColorReplacement: (() -> String)? = null
) = resourcePatch { ) = resourcePatch {
apply { apply {
// After patch option validators are fixed https://github.com/ReVanced/revanced-patcher/issues/372 // 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 val darkColor by darkThemeBackgroundColorOption
if (!validateColorName(darkColor!!)) { if (!validateColorName(darkColor!!)) {
throw PatchException("Invalid dark theme color: $darkColor") throw PatchException("Invalid dark theme color: $darkColor")

View file

@ -1,17 +1,19 @@
package app.revanced.patches.shared.misc.checks package app.revanced.patches.shared.misc.checks
import android.os.Build.* import android.os.Build.*
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.bytecodePatch 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.MutableEncodedValue
import com.android.tools.smali.dexlib2.iface.value.MutableLongEncodedValue import com.android.tools.smali.dexlib2.iface.value.MutableLongEncodedValue
import com.android.tools.smali.dexlib2.iface.value.MutableStringEncodedValue 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.ImmutableLongEncodedValue
import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue 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.nio.charset.StandardCharsets
import java.security.MessageDigest import java.security.MessageDigest
import kotlin.io.encoding.Base64 import kotlin.io.encoding.Base64
@ -21,7 +23,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/checks/CheckEnvironmentPatch;" "Lapp/revanced/extension/shared/checks/CheckEnvironmentPatch;"
fun checkEnvironmentPatch( fun checkEnvironmentPatch(
mainActivityOnCreateFingerprint: Fingerprint, getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
extensionPatch: Patch, extensionPatch: Patch,
vararg compatiblePackages: String, vararg compatiblePackages: String,
) = bytecodePatch( ) = bytecodePatch(
@ -38,20 +40,20 @@ fun checkEnvironmentPatch(
addResources("shared", "misc.checks.checkEnvironmentPatch") addResources("shared", "misc.checks.checkEnvironmentPatch")
fun setPatchInfo() { fun setPatchInfo() {
fun <T : MutableEncodedValue> Fingerprint.setClassFields(vararg fieldNameValues: Pair<String, T>) { fun <T : MutableEncodedValue> MutableClassDef.setClassFields(vararg fieldNameValues: Pair<String, T>) {
val fieldNameValueMap = mapOf(*fieldNameValues) val fieldNameValueMap = mapOf(*fieldNameValues)
classDef.fields.forEach { field -> fields.forEach { field ->
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
} }
} }
patchInfoFingerprint.setClassFields( patchInfoClassDef.setClassFields(
"PATCH_TIME" to System.currentTimeMillis().encoded, "PATCH_TIME" to System.currentTimeMillis().encoded,
) )
fun setBuildInfo() { fun setBuildInfo() {
patchInfoBuildFingerprint.setClassFields( patchInfoBuildClassDef.setClassFields(
"PATCH_BOARD" to BOARD.encodedAndHashed, "PATCH_BOARD" to BOARD.encodedAndHashed,
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed, "PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
"PATCH_BRAND" to BRAND.encodedAndHashed, "PATCH_BRAND" to BRAND.encodedAndHashed,
@ -82,7 +84,7 @@ fun checkEnvironmentPatch(
} }
} }
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstruction( fun invokeCheck() = getMainActivityOnCreateMethod().addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V", "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
) )

View file

@ -1,11 +1,12 @@
package app.revanced.patches.shared.misc.checks 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 { internal val BytecodePatchContext.patchInfoClassDef by gettingFirstMutableClassDefDeclaratively(
custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo;" } "Lapp/revanced/extension/shared/checks/PatchInfo;"
} )
internal val patchInfoBuildFingerprint = fingerprint { internal val BytecodePatchContext.patchInfoBuildClassDef by gettingFirstMutableClassDefDeclaratively(
custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo\$Build;" } $$"Lapp/revanced/extension/shared/checks/PatchInfo$Build;"
} )

View file

@ -2,23 +2,16 @@ package app.revanced.patches.shared.misc.debugging
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.immutableClassDef
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch 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.*
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.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.util.*
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 com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@ -45,7 +38,8 @@ internal fun enableDebuggingPatch(
apply { apply {
copyResources( copyResources(
"settings", "settings",
ResourceGroup("drawable", ResourceGroup(
"drawable",
// Action buttons. // Action buttons.
"revanced_settings_copy_all.xml", "revanced_settings_copy_all.xml",
"revanced_settings_deselect_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. // Hook the methods that look up if a feature flag is active.
experimentalBooleanFeatureFlagFingerprint.match( experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalBooleanFeatureFlagMethod().apply {
experimentalFeatureFlagParentFingerprint.originalClassDef
).method.apply {
findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index -> findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index ->
val register = getInstruction<OneRegisterInstruction>(index).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA
@ -121,15 +113,13 @@ internal fun enableDebuggingPatch(
} }
} }
experimentalDoubleFeatureFlagFingerprint.match( experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalDoubleFeatureFlagMethod().apply {
experimentalFeatureFlagParentFingerprint.originalClassDef
).method.apply {
val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE)
addInstructions( addInstructions(
insertIndex, 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 invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isDoubleFeatureFlagEnabled(DJD)D
move-result-wide v0 move-result-wide v0
return-wide v0 return-wide v0
@ -137,9 +127,7 @@ internal fun enableDebuggingPatch(
) )
} }
experimentalLongFeatureFlagFingerprint.match( experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalLongFeatureFlagMethod().apply {
experimentalFeatureFlagParentFingerprint.originalClassDef
).method.apply {
val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE)
addInstructions( addInstructions(
@ -153,21 +141,20 @@ internal fun enableDebuggingPatch(
) )
} }
if (hookStringFeatureFlag) experimentalStringFeatureFlagFingerprint.match( if (hookStringFeatureFlag)
experimentalFeatureFlagParentFingerprint.originalClassDef experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalStringFeatureFlagMethod().apply {
).method.apply { val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT)
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT)
addInstructions( addInstructions(
insertIndex, insertIndex,
""" """
move-result-object v0 move-result-object v0
invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String; invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String;
move-result-object v0 move-result-object v0
return-object v0 return-object v0
""" """
) )
} }
// There exists other experimental accessor methods for byte[] // There exists other experimental accessor methods for byte[]
// and wrappers for obfuscated classes, but currently none of those are hooked. // and wrappers for obfuscated classes, but currently none of those are hooked.

View file

@ -1,35 +1,46 @@
package app.revanced.patches.shared.misc.debugging 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.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) accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("L") returnType("L")
parameters("L", "J", "[B") parameterTypes("L", "J", "[B")
strings("Unable to parse proto typed experiment flag: ")
} }
internal val experimentalBooleanFeatureFlagFingerprint = fingerprint { context(_: BytecodePatchContext)
internal fun ClassDef.getExperimentalBooleanFeatureFlagMethod() = firstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Z") returnType("Z")
parameters("L", "J", "Z") parameterTypes("L", "J", "Z")
} }
internal val experimentalDoubleFeatureFlagFingerprint = fingerprint { context(_: BytecodePatchContext)
internal fun ClassDef.getExperimentalDoubleFeatureFlagMethod() = firstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("D") returnType("D")
parameters("J", "D") parameterTypes("J", "D")
} }
internal val experimentalLongFeatureFlagFingerprint = fingerprint { context(_: BytecodePatchContext)
internal fun ClassDef.getExperimentalLongFeatureFlagMethod() = firstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("J") returnType("J")
parameters("J", "J") parameterTypes("J", "J")
} }
internal val experimentalStringFeatureFlagFingerprint = fingerprint { context(_: BytecodePatchContext)
internal fun ClassDef.getExperimentalStringFeatureFlagMethod() = firstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/String;") returnType("Ljava/lang/String;")
parameters("J", "Ljava/lang/String;") parameterTypes("J", "Ljava/lang/String;")
} }

View file

@ -1,11 +1,11 @@
package app.revanced.patches.shared.misc.dns package app.revanced.patches.shared.misc.dns
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import com.android.tools.smali.dexlib2.mutable.MutableMethod
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/patches/CheckWatchHistoryDomainNameResolutionPatch;" "Lapp/revanced/extension/shared/patches/CheckWatchHistoryDomainNameResolutionPatch;"
@ -16,7 +16,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
internal fun checkWatchHistoryDomainNameResolutionPatch( internal fun checkWatchHistoryDomainNameResolutionPatch(
block: BytecodePatchBuilder.() -> Unit = {}, block: BytecodePatchBuilder.() -> Unit = {},
executeBlock: BytecodePatchContext.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {},
mainActivityFingerprint: Fingerprint getMainActivityMethod: BytecodePatchContext.() -> MutableMethod
) = bytecodePatch( ) = bytecodePatch(
name = "Check watch history domain name resolution", name = "Check watch history domain name resolution",
description = "Checks if the device DNS server is preventing user watch history from being saved.", 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") addResources("shared", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
mainActivityFingerprint.method.addInstruction( getMainActivityMethod().addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V", "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
) )

View file

@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.instructions
import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.* 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.changePackageNamePatch
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources

View file

@ -1,11 +1,11 @@
package app.revanced.patches.spotify.misc.check package app.revanced.patches.spotify.misc.check
import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch 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.misc.extension.sharedExtensionPatch
import app.revanced.patches.spotify.shared.mainActivityOnCreateMethod
internal val checkEnvironmentPatch = checkEnvironmentPatch( internal val checkEnvironmentPatch = checkEnvironmentPatch(
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { mainActivityOnCreateMethod },
extensionPatch = sharedExtensionPatch, extensionPatch = sharedExtensionPatch,
"com.spotify.music", "com.spotify.music",
) )

View file

@ -2,13 +2,13 @@ package app.revanced.patches.spotify.misc.extension
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patches.shared.misc.extension.extensionHook 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.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
internal val mainActivityOnCreateHook = extensionHook { mainActivityOnCreateFingerprint } internal val mainActivityOnCreateHook = extensionHook { mainActivityOnCreateMethod }
internal val loadOrbitLibraryHook = extensionHook { internal val loadOrbitLibraryHook = extensionHook {
// FIXME: Creating this is a mess and needs refactoring. // FIXME: Creating this is a mess and needs refactoring.

View file

@ -1,15 +1,21 @@
package app.revanced.patches.spotify.shared 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.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 import com.android.tools.smali.dexlib2.AccessFlags
private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivity;" 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) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V") returnType("V")
parameters("Landroid/os/Bundle;") parameterTypes("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.type == SPOTIFY_MAIN_ACTIVITY
}
} }

View file

@ -1,5 +1,8 @@
package app.revanced.patches.tiktok.misc.extension 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.activityOnCreateExtensionHook
import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.patches.shared.misc.extension.extensionHook
@ -16,19 +19,15 @@ internal val initHook = activityOnCreateExtensionHook(
internal val jatoInitHook = extensionHook( internal val jatoInitHook = extensionHook(
getContextRegister = { "p1" } getContextRegister = { "p1" }
) { ) {
parameters("Landroid/content/Context;") name("run")
custom { method, classDef -> definingClass("Lcom/ss/android/ugc/aweme/legoImp/task/JatoInitTask;")
classDef.type == "Lcom/ss/android/ugc/aweme/legoImp/task/JatoInitTask;" && parameterTypes("Landroid/content/Context;")
method.name == "run"
}
} }
internal val storeRegionInitHook = extensionHook( internal val storeRegionInitHook = extensionHook(
getContextRegister = { "p1" } getContextRegister = { "p1" }
) { ) {
parameters("Landroid/content/Context;") name("run")
custom { method, classDef -> definingClass("Lcom/ss/android/ugc/aweme/legoImp/task/StoreRegionInitTask;")
classDef.type == "Lcom/ss/android/ugc/aweme/legoImp/task/StoreRegionInitTask;" && parameterTypes("Landroid/content/Context;")
method.name == "run"
}
} }

View file

@ -1,8 +1,8 @@
package app.revanced.patches.twitter.misc.hook package app.revanced.patches.twitter.misc.hook
import app.revanced.patcher.patch.bytecodePatch 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.addJsonHook
import app.revanced.patches.twitter.misc.hook.json.jsonHook
import app.revanced.patches.twitter.misc.hook.json.jsonHookPatch import app.revanced.patches.twitter.misc.hook.json.jsonHookPatch
fun hookPatch( fun hookPatch(
@ -19,6 +19,6 @@ fun hookPatch(
) )
apply { apply {
addJsonHook(JsonHook(hookClassDescriptor)) addJsonHook(jsonHook(hookClassDescriptor))
} }
} }

View file

@ -1,27 +1,29 @@
package app.revanced.patches.twitter.misc.hook.json 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.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
internal val jsonHookPatchFingerprint = fingerprint { internal val jsonHookPatchMethodMatch = firstMethodComposite {
opcodes( name("<clinit>")
Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list. instructions(
Opcode.INVOKE_INTERFACE(), // Add dummy hook to hooks list.
// Add hooks to the hooks list. // Add hooks to the hooks list.
Opcode.INVOKE_STATIC, // Call buildList. Opcode.INVOKE_STATIC(), // Call buildList.
) )
custom { method, _ -> method.name == "<clinit>" }
} }
internal val jsonInputStreamFingerprint = fingerprint { context(_: BytecodePatchContext)
custom { method, _ -> internal fun ClassDef.getJsonInputStreamMethod() = firstMutableMethodDeclaratively {
if (method.parameterTypes.isEmpty()) { custom {
false if (parameterTypes.isEmpty()) false
} else { else parameterTypes.first() == "Ljava/io/InputStream;"
method.parameterTypes.first() == "Ljava/io/InputStream;"
}
} }
} }
internal val loganSquareFingerprint = fingerprint { internal val BytecodePatchContext.loganSquareClassDef by gettingFirstClassDef {
custom { _, classDef -> classDef.endsWith("LoganSquare;") } type.endsWith("LoganSquare;")
} }

View file

@ -1,8 +1,8 @@
package app.revanced.patches.twitter.misc.hook.json 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.addInstructions
import app.revanced.patcher.extensions.removeInstructions import app.revanced.patcher.extensions.removeInstructions
import app.revanced.patcher.firstClassDef
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
@ -15,24 +15,21 @@ import java.io.InvalidClassException
* *
* @param jsonHook The [JsonHook] to add. * @param jsonHook The [JsonHook] to add.
*/ */
context(BytecodePatchContext) fun BytecodePatchContext.addJsonHook(
fun addJsonHook(
jsonHook: JsonHook, jsonHook: JsonHook,
) { ) {
if (jsonHook.added) return if (jsonHook.added) return
jsonHookPatchFingerprint.method.apply { // Insert hooks right before calling buildList.
// Insert hooks right before calling buildList. val insertIndex = jsonHookPatchMethodMatch.indices.last()
val insertIndex = jsonHookPatchFingerprint.instructionMatches.last().index
addInstructions( jsonHookPatchMethodMatch.method.addInstructions(
insertIndex, insertIndex,
""" """
sget-object v1, ${jsonHook.descriptor}->INSTANCE:${jsonHook.descriptor} sget-object v1, ${jsonHook.descriptor}->INSTANCE:${jsonHook.descriptor}
invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
""", """,
) )
}
jsonHook.added = true jsonHook.added = true
} }
@ -48,15 +45,13 @@ val jsonHookPatch = bytecodePatch(
dependsOn(sharedExtensionPatch) dependsOn(sharedExtensionPatch)
apply { apply {
jsonHookPatchFingerprint.apply { jsonHookPatchMethodMatch.apply {
val jsonHookPatch = firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR) match(firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR)).methodOrNull
matchOrNull(jsonHookPatch)
?: throw PatchException("Unexpected extension.") ?: throw PatchException("Unexpected extension.")
} }
val jsonFactoryClassDef = 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 .fields
.firstOrNull { it.name == "JSON_FACTORY" } .firstOrNull { it.name == "JSON_FACTORY" }
?.type ?.type
@ -64,7 +59,7 @@ val jsonHookPatch = bytecodePatch(
?: throw PatchException("Could not find required class.") ?: throw PatchException("Could not find required class.")
// Hook the methods first parameter. // Hook the methods first parameter.
jsonInputStreamFingerprint.match(jsonFactoryClassDef).method.addInstructions( jsonFactoryClassDef.getJsonInputStreamMethod().addInstructions(
0, 0,
""" """
invoke-static { p1 }, $JSON_HOOK_PATCH_CLASS_DESCRIPTOR->parseJsonHook(Ljava/io/InputStream;)Ljava/io/InputStream; invoke-static { p1 }, $JSON_HOOK_PATCH_CLASS_DESCRIPTOR->parseJsonHook(Ljava/io/InputStream;)Ljava/io/InputStream;
@ -75,14 +70,19 @@ val jsonHookPatch = bytecodePatch(
afterDependents { afterDependents {
// Remove hooks.add(dummyHook). // Remove hooks.add(dummyHook).
jsonHookPatchFingerprint.method.apply { val addDummyHookIndex = jsonHookPatchMethodMatch.indices.last()
val addDummyHookIndex = jsonHookPatchFingerprint.instructionMatches.last().index - 2
removeInstructions(addDummyHookIndex, 2) jsonHookPatchMethodMatch.method.removeInstructions(addDummyHookIndex, 2)
}
} }
} }
class JsonHook internal constructor(
internal val descriptor: String,
) {
internal var added = false
}
/** /**
* Create a hook class. * Create a hook class.
* The class has to extend on **JsonHook**. * The class has to extend on **JsonHook**.
@ -91,22 +91,18 @@ val jsonHookPatch = bytecodePatch(
* @param descriptor The class descriptor of the hook. * @param descriptor The class descriptor of the hook.
* @throws ClassNotFoundException If the class could not be found. * @throws ClassNotFoundException If the class could not be found.
*/ */
context(BytecodePatchContext) context(_: BytecodePatchContext)
class JsonHook( fun jsonHook(descriptor: String): JsonHook {
internal val descriptor: String, firstClassDef(descriptor).let {
) { it.also { classDef ->
internal var added = false if (
classDef.superclass != JSON_HOOK_CLASS_DESCRIPTOR ||
init { !classDef.fields.any { field -> field.name == "INSTANCE" }
firstClassDef(descriptor).let { ) {
it.also { classDef -> throw InvalidClassException(classDef.type, "Not a hook class")
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)
}

View file

@ -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.playercontrols.playerControlsPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch 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.patches.youtube.video.information.videoInformationPatch
import app.revanced.util.ResourceGroup import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources import app.revanced.util.copyResources
@ -85,7 +85,7 @@ val downloadsPatch = bytecodePatch(
injectVisibilityCheckCall(BUTTON_DESCRIPTOR) injectVisibilityCheckCall(BUTTON_DESCRIPTOR)
// Main activity is used to launch downloader intent. // Main activity is used to launch downloader intent.
mainActivityOnCreateFingerprint.method.addInstruction( mainActivityOnCreateMethod.method.addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->setMainActivity(Landroid/app/Activity;)V" "invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->setMainActivity(Landroid/app/Activity;)V"
) )

View file

@ -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_MAIN_ACTIVITY_NAME
import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_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.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
@Suppress("unused") @Suppress("unused")
val customBrandingPatch = baseCustomBrandingPatch( val customBrandingPatch = baseCustomBrandingPatch(

View file

@ -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.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater 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_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.is_20_34_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch 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.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.insertLiteralOverride import app.revanced.util.insertLiteralOverride
@ -155,7 +154,7 @@ val seekbarColorPatch = bytecodePatch(
} }
// Hook the splash animation to set the a seekbar color. // Hook the splash animation to set the a seekbar color.
mainActivityOnCreateFingerprint.method.apply { mainActivityOnCreateMethod.method.apply {
val setAnimationIntMethodName = val setAnimationIntMethodName =
lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name

View file

@ -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.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch 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.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@ -65,7 +65,7 @@ val shortsAutoplayPatch = bytecodePatch(
} }
// Main activity is used to check if app is in pip mode. // Main activity is used to check if app is in pip mode.
mainActivityOnCreateFingerprint.method.addInstruction( mainActivityOnCreateMethod.method.addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V", "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V",
) )

View file

@ -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.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch 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.findFreeRegister
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@ -61,7 +61,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
) )
// Activity is used as the context to launch an Intent. // Activity is used as the context to launch an Intent.
mainActivityOnCreateFingerprint.method.addInstruction( mainActivityOnCreateMethod.method.addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" + "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
"setMainActivity(Landroid/app/Activity;)V", "setMainActivity(Landroid/app/Activity;)V",

View file

@ -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.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch 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 = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/announcements/AnnouncementsPatch;" "Lapp/revanced/extension/youtube/patches/announcements/AnnouncementsPatch;"
@ -37,7 +37,7 @@ val announcementsPatch = bytecodePatch(
SwitchPreference("revanced_announcements"), SwitchPreference("revanced_announcements"),
) )
mainActivityOnCreateFingerprint.method.addInstruction( mainActivityOnCreateMethod.method.addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V", "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
) )

View file

@ -2,10 +2,10 @@ package app.revanced.patches.youtube.misc.check
import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch import app.revanced.patches.shared.misc.checks.checkEnvironmentPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch 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( internal val checkEnvironmentPatch = checkEnvironmentPatch(
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { mainActivityOnCreateMethod },
extensionPatch = sharedExtensionPatch, extensionPatch = sharedExtensionPatch,
"com.google.android.youtube", "com.google.android.youtube",
) )

View file

@ -2,7 +2,6 @@ package app.revanced.patches.youtube.misc.dns
import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch( val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch(
block = { block = {
@ -19,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso
) )
) )
}, },
mainActivityFingerprint = mainActivityOnCreateFingerprint getMainActivityMethod = mainActivityOnCreateFingerprint
) )

View file

@ -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.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.misc.spoof.spoofVideoStreamsPatch import app.revanced.patches.youtube.misc.spoof.spoofVideoStreamsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
@Suppress("unused") @Suppress("unused")
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(

View file

@ -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.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
val spoofVideoStreamsPatch = spoofVideoStreamsPatch( val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;", extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;",

View file

@ -1,5 +1,7 @@
package app.revanced.patches.youtube.shared 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.InstructionLocation.MatchAfterImmediately
import app.revanced.patcher.fieldAccess import app.revanced.patcher.fieldAccess
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
@ -8,6 +10,11 @@ import app.revanced.patcher.methodCall
import app.revanced.patcher.newInstance import app.revanced.patcher.newInstance
import app.revanced.patcher.opcode import app.revanced.patcher.opcode
import app.revanced.patcher.addString 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.ResourceType
import app.revanced.patches.shared.misc.mapping.resourceLiteral import app.revanced.patches.shared.misc.mapping.resourceLiteral
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
@ -58,12 +65,11 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint {
} }
} }
internal val mainActivityOnCreateFingerprint = fingerprint { internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
returns("V") name("onCreate")
parameters("Landroid/os/Bundle;") definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE)
custom { method, classDef -> returnType("V")
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE parameterTypes("Landroid/os/Bundle;")
}
} }
internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint { internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint {
@ -87,8 +93,8 @@ internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint {
) )
custom { _, classDef -> custom { _, classDef ->
classDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;" || classDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;" ||
classDef.superclass == classDef.superclass ==
"Lcom/google/android/libraries/youtube/rendering/ui/spec/typography/YouTubeAppCompatTextView;" "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;"), newInstance("Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"),
opcode(Opcode.IGET_OBJECT), opcode(Opcode.IGET_OBJECT),
opcode(Opcode.CHECK_CAST), 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).
) )
} }

View file

@ -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.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
@Suppress("unused") @Suppress("unused")
val forceOriginalAudioPatch = forceOriginalAudioPatch( val forceOriginalAudioPatch = forceOriginalAudioPatch(