mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-22 18:23:59 +00:00
some more progress
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.googlenews.misc.extension.extensionPatch
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.MAGAZINES_PACKAGE_NAME
|
||||
@@ -11,7 +12,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch
|
||||
val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
fromPackageName = MAGAZINES_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
|
||||
getMainActivityOnCreateMethod = { magazinesActivityOnCreateMethod },
|
||||
getMainActivityOnCreateMethod = BytecodePatchContext::magazinesActivityOnCreateMethod::get,
|
||||
extensionPatch = extensionPatch,
|
||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||
) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.googlephotos.misc.extension.extensionPatch
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.PHOTOS_PACKAGE_NAME
|
||||
@@ -10,7 +11,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||
val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
fromPackageName = PHOTOS_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
|
||||
getMainActivityOnCreateMethod = { homeActivityOnCreateMethod },
|
||||
getMainActivityOnCreateMethod = BytecodePatchContext::homeActivityOnCreateMethod::get,
|
||||
extensionPatch = extensionPatch,
|
||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.music.misc.gms
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.music.misc.settings
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.parameterTypes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.music.shared
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.parameterTypes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.myexpenses.misc.pro
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.myfitnesspal.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.nunl.ads
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.nunl.firebase
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.openinghours.misc.fix.crash
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.parameterTypes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.orfon.detection.root
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.pandora.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.pandora.misc
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.peacocktv.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.photomath.detection.deviceid
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.parameterTypes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.photomath.misc.annoyances
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.photomath.misc.unlock.bookpoint
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.photomath.misc.unlock.plus
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.piccomafr.tracking
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.pixiv.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.primevideo.ads
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.primevideo.video.speed
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.protonvpn.delay
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.rar.misc.annoyances.purchasereminder
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.ad.comments
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.ad.general
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.parameterTypes
|
||||
|
||||
@@ -3,15 +3,15 @@ package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
|
||||
import app.revanced.patcher.extensions.typeReference
|
||||
import app.revanced.patches.reddit.customclients.INSTALL_NEW_CLIENT_METHOD
|
||||
import app.revanced.patches.reddit.customclients.baconreader.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/baconreader/FixRedgifsApiPatch;"
|
||||
|
||||
@@ -29,15 +29,16 @@ val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
|
||||
// Remove conflicting OkHttp interceptors.
|
||||
val originalInterceptorInstallIndex = getOkHttpClientMethod.indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type == "Lcom/onelouder/baconreader/media/gfycat/RedGifsManager\$HeaderInterceptor;"
|
||||
opcode == Opcode.NEW_INSTANCE && typeReference?.type == $$"Lcom/onelouder/baconreader/media/gfycat/RedGifsManager$HeaderInterceptor;"
|
||||
}
|
||||
getOkHttpClientMethod.removeInstructions(originalInterceptorInstallIndex, 5)
|
||||
|
||||
val index = getOkHttpClientMethod.indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
|
||||
reference?.name == "build" && reference.definingClass == $$"Lokhttp3/OkHttpClient$Builder;"
|
||||
}
|
||||
val register = getOkHttpClientMethod.getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
|
||||
getOkHttpClientMethod.replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val BytecodePatchContext.maxMediationMethod by gettingFirstMutableMethodDeclaratively(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.api
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.fix.slink
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.infinityforreddit.api
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val BytecodePatchContext.apiUtilsMethod by gettingFirstMutableMethod("native-lib")
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.reddit.customclients.infinityforreddit.subscription
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.InstructionMatchingFunctions.invoke
|
||||
import app.revanced.patcher.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.api
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.InstructionMatchingFunctions.invoke
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.instructions
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.redditisfun.api
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.relayforreddit.api
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.slide.api
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.ads
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.detection.piracy
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclarativelyOrNull
|
||||
import app.revanced.patcher.InstructionMatchingFunctions.invoke
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclarativelyOrNull
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.custom
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.annoyances.startup
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.api
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.string
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.string
|
||||
|
||||
internal val getAuthorizationStringMethodMatch = firstMethodComposite {
|
||||
instructions(string("authorize.compact?client_id"::startsWith))
|
||||
|
||||
@@ -1,40 +1,39 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.writeRegister
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11n
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
|
||||
internal val createOkHttpClientFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.createOkHttpClientMethod by gettingFirstMutableMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
returnType("V")
|
||||
parameterTypes()
|
||||
custom {
|
||||
// There are four functions (each creating a client) defined in this file with very similar fingerprints.
|
||||
// We're looking for the one that only creates one object (the builder) and sets client options true
|
||||
// (thus never reloading the register with a 0).
|
||||
classDef.sourceFile == "OkHttpHelper.java" &&
|
||||
method.instructions.count { it.opcode == Opcode.NEW_INSTANCE } == 1 &&
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.CONST_4 && writeRegister == 1 && (this as Instruction11n).narrowLiteral == 0
|
||||
immutableClassDef.sourceFile == "OkHttpHelper.java" && instructions.count {
|
||||
it.opcode == Opcode.NEW_INSTANCE
|
||||
} == 1 && indexOfFirstInstruction {
|
||||
opcode == Opcode.CONST_4 && writeRegister == 1 && (this as NarrowLiteralInstruction).narrowLiteral == 0
|
||||
} == -1
|
||||
}
|
||||
}
|
||||
|
||||
internal val getDefaultUserAgentFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "getDefaultUserAgent" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
internal val BytecodePatchContext.getDefaultUserAgentMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("getDefaultUserAgent")
|
||||
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||
}
|
||||
|
||||
internal val getOriginalUserAgentFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getOriginalUserAgentMethod by gettingFirstMutableMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { _, classDef -> classDef.sourceFile == "AccountSingleton.java" }
|
||||
returnType("Ljava/lang/String;"::startsWith)
|
||||
parameterTypes()
|
||||
custom { immutableClassDef.sourceFile == "AccountSingleton.java" }
|
||||
}
|
||||
|
||||
@@ -26,30 +26,27 @@ val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
apply {
|
||||
// region Patch Redgifs OkHttp3 client.
|
||||
|
||||
createOkHttpClientFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
|
||||
}
|
||||
val register = getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
|
||||
"""
|
||||
)
|
||||
val index = createOkHttpClientMethod.indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == $$"Lokhttp3/OkHttpClient$Builder;"
|
||||
}
|
||||
val register = createOkHttpClientMethod.getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
|
||||
getDefaultUserAgentFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, ${getOriginalUserAgentFingerprint.method}
|
||||
move-result-object v0
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
createOkHttpClientMethod.replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
|
||||
"""
|
||||
)
|
||||
|
||||
getDefaultUserAgentMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $getOriginalUserAgentMethod
|
||||
move-result-object v0
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.slink
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMutableMethod
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val linkHelperOpenLinkFingerprint = fingerprint {
|
||||
strings("Link title: ")
|
||||
}
|
||||
|
||||
internal val setAuthorizationHeaderFingerprint = fingerprint {
|
||||
returns("Ljava/util/HashMap;")
|
||||
strings("Authorization", "bearer ")
|
||||
custom { method, _ -> method.definingClass == "Lcom/laurencedawson/reddit_sync/singleton/a;" }
|
||||
internal val BytecodePatchContext.linkHelperOpenLinkMethod by gettingFirstMutableMethod("Link title: ")
|
||||
|
||||
internal val BytecodePatchContext.setAuthorizationHeaderMethod by gettingFirstMutableMethodDeclaratively(
|
||||
"Authorization", "bearer "
|
||||
) {
|
||||
definingClass("Lcom/laurencedawson/reddit_sync/singleton/a;")
|
||||
returnType("Ljava/util/HashMap;"::equals)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.slink
|
||||
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patches.reddit.customclients.RESOLVE_S_LINK_METHOD
|
||||
import app.revanced.patches.reddit.customclients.SET_ACCESS_TOKEN_METHOD
|
||||
import app.revanced.patches.reddit.customclients.fixSLinksPatch
|
||||
@@ -24,27 +24,25 @@ val fixSLinksPatch = fixSLinksPatch(
|
||||
apply {
|
||||
// region Patch navigation handler.
|
||||
|
||||
linkHelperOpenLinkFingerprint.method.apply {
|
||||
val urlRegister = "p3"
|
||||
val tempRegister = "v2"
|
||||
val urlRegister = "p3"
|
||||
val tempRegister = "v2"
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { $urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->$RESOLVE_S_LINK_METHOD
|
||||
move-result $tempRegister
|
||||
if-eqz $tempRegister, :continue
|
||||
return $tempRegister
|
||||
""",
|
||||
ExternalLabel("continue", getInstruction(0)),
|
||||
)
|
||||
}
|
||||
linkHelperOpenLinkMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { $urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->$RESOLVE_S_LINK_METHOD
|
||||
move-result $tempRegister
|
||||
if-eqz $tempRegister, :continue
|
||||
return $tempRegister
|
||||
""",
|
||||
ExternalLabel("continue", linkHelperOpenLinkMethod.getInstruction(0)),
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch set access token.
|
||||
|
||||
setAuthorizationHeaderFingerprint.method.addInstruction(
|
||||
setAuthorizationHeaderMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
|
||||
)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.thumbnail
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val customImageViewLoadFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.customImageViewLoadMethod by gettingFirstMutableMethodDeclaratively {
|
||||
definingClass("CustomImageView;"::endsWith)
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
parameters("Ljava/lang/String;", "Z", "Z", "I", "I")
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("CustomImageView;")
|
||||
}
|
||||
parameterTypes("Ljava/lang/String;", "Z", "Z", "I", "I")
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.thumbnail
|
||||
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
val fixPostThumbnailsPatch = bytecodePatch(
|
||||
name = "Fix post thumbnails",
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Fix post thumbnails` by creatingBytecodePatch(
|
||||
description = "Fixes loading post thumbnails by correcting their URLs.",
|
||||
) {
|
||||
|
||||
@@ -17,7 +16,7 @@ val fixPostThumbnailsPatch = bytecodePatch(
|
||||
|
||||
// Image URLs contain escaped ampersands (&), let's replace these with unescaped ones (&).
|
||||
apply {
|
||||
customImageViewLoadFingerprint.method.addInstructions(
|
||||
customImageViewLoadMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# url = url.replace("&", "&");
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.user
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal fun userEndpointFingerprint(source: String, accessFlags: Set<AccessFlags>? = null) = fingerprint {
|
||||
strings("u/")
|
||||
custom { _, classDef -> classDef.sourceFile == source }
|
||||
accessFlags(*accessFlags?.toTypedArray() ?: return@fingerprint)
|
||||
internal fun userEndpointMethodMatch(
|
||||
source: String,
|
||||
accessFlags: Set<AccessFlags>? = null
|
||||
) = firstMethodComposite {
|
||||
instructions("u/"(String::contains))
|
||||
custom { immutableClassDef.sourceFile == source }
|
||||
accessFlags(*accessFlags?.toTypedArray() ?: return@firstMethodComposite)
|
||||
}
|
||||
|
||||
internal val oAuthFriendRequestFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthFriendRequestMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthFriendRequest.java",
|
||||
)
|
||||
|
||||
internal val oAuthUnfriendRequestFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthUnfriendRequestMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthUnfriendRequest.java",
|
||||
)
|
||||
|
||||
internal val oAuthUserIdRequestFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthUserIdRequestMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthUserIdRequest.java",
|
||||
)
|
||||
|
||||
internal val oAuthUserInfoRequestFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthUserInfoRequestMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthUserInfoRequest.java",
|
||||
)
|
||||
|
||||
internal val oAuthSubredditInfoRequestConstructorFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthSubredditInfoRequestConstructorMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthSubredditInfoRequest.java",
|
||||
setOf(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR),
|
||||
)
|
||||
|
||||
internal val oAuthSubredditInfoRequestHelperFingerprint = userEndpointFingerprint(
|
||||
internal val oAuthSubredditInfoRequestHelperMethodMatch = userEndpointMethodMatch(
|
||||
"OAuthSubredditInfoRequest.java",
|
||||
setOf(AccessFlags.PRIVATE, AccessFlags.STATIC),
|
||||
)
|
||||
|
||||
@@ -2,10 +2,9 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.user
|
||||
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.stringReference
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
@Suppress("unused")
|
||||
val useUserEndpointPatch = bytecodePatch(
|
||||
@@ -13,7 +12,7 @@ val useUserEndpointPatch = bytecodePatch(
|
||||
description = "Replaces the deprecated endpoint for viewing user profiles /u with /user, that used to fix a bug.",
|
||||
use = false,
|
||||
|
||||
) {
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.laurencedawson.reddit_sync",
|
||||
"com.laurencedawson.reddit_sync.pro",
|
||||
@@ -22,20 +21,19 @@ val useUserEndpointPatch = bytecodePatch(
|
||||
|
||||
apply {
|
||||
arrayOf(
|
||||
oAuthFriendRequestFingerprint,
|
||||
oAuthSubredditInfoRequestConstructorFingerprint,
|
||||
oAuthSubredditInfoRequestHelperFingerprint,
|
||||
oAuthUnfriendRequestFingerprint,
|
||||
oAuthUserIdRequestFingerprint,
|
||||
oAuthUserInfoRequestFingerprint,
|
||||
).map { fingerprint ->
|
||||
fingerprint.stringMatches.first().index to fingerprint.method
|
||||
oAuthFriendRequestMethodMatch,
|
||||
oAuthSubredditInfoRequestConstructorMethodMatch,
|
||||
oAuthSubredditInfoRequestHelperMethodMatch,
|
||||
oAuthUnfriendRequestMethodMatch,
|
||||
oAuthUserIdRequestMethodMatch,
|
||||
oAuthUserInfoRequestMethodMatch
|
||||
).map { match ->
|
||||
match.stringIndices.values.first() to match.method
|
||||
}.forEach { (userPathStringIndex, method) ->
|
||||
val userPathStringInstruction = method.getInstruction<OneRegisterInstruction>(userPathStringIndex)
|
||||
|
||||
val userPathStringRegister = userPathStringInstruction.registerA
|
||||
val fixedUserPathString = userPathStringInstruction.getReference<StringReference>()!!
|
||||
.string.replace("u/", "user/")
|
||||
val fixedUserPathString = userPathStringInstruction.stringReference!!.string.replace("u/", "user/")
|
||||
|
||||
method.replaceInstruction(
|
||||
userPathStringIndex,
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.video
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val parseRedditVideoNetworkResponseFingerprint = fingerprint {
|
||||
internal val parseRedditVideoNetworkResponseMethodMatch = firstMethodComposite {
|
||||
name("parseNetworkResponse")
|
||||
opcodes(
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.CONST_WIDE_32,
|
||||
)
|
||||
custom { methodDef, classDef ->
|
||||
classDef.sourceFile == "RedditVideoRequest.java" && methodDef.name == "parseNetworkResponse"
|
||||
}
|
||||
custom { immutableClassDef.sourceFile == "RedditVideoRequest.java" }
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@ val fixVideoDownloadsPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
apply {
|
||||
val scanResult = parseRedditVideoNetworkResponseFingerprint.instructionMatches
|
||||
val newInstanceIndex = scanResult.first().index
|
||||
val invokeDirectIndex = scanResult.last().index - 1
|
||||
val scanResult = parseRedditVideoNetworkResponseMethodMatch.indices
|
||||
val newInstanceIndex = scanResult.first()
|
||||
val invokeDirectIndex = scanResult.last() - 1
|
||||
|
||||
val buildResponseInstruction =
|
||||
parseRedditVideoNetworkResponseFingerprint.method.getInstruction<Instruction35c>(invokeDirectIndex)
|
||||
parseRedditVideoNetworkResponseMethodMatch.method.getInstruction<Instruction35c>(invokeDirectIndex)
|
||||
|
||||
parseRedditVideoNetworkResponseFingerprint.method.addInstructions(
|
||||
parseRedditVideoNetworkResponseMethodMatch.method.addInstructions(
|
||||
newInstanceIndex + 1,
|
||||
"""
|
||||
# Get byte array from response.
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package app.revanced.patches.reddit.layout.disablescreenshotpopup
|
||||
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
val disableScreenshotPopupPatch = bytecodePatch(
|
||||
name = "Disable screenshot popup",
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Disable screenshot popup` by creatingBytecodePatch(
|
||||
description = "Disables the popup that shows up when taking a screenshot.",
|
||||
) {
|
||||
compatibleWith("com.reddit.frontpage")
|
||||
|
||||
apply {
|
||||
disableScreenshotPopupFingerprint.method.addInstruction(0, "return-void")
|
||||
disableScreenshotPopupMethod.addInstruction(0, "return-void")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package app.revanced.patches.reddit.layout.disablescreenshotpopup
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
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
|
||||
|
||||
internal val disableScreenshotPopupFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroidx/compose/runtime/", "I")
|
||||
custom { method, classDef ->
|
||||
if (!classDef.endsWith("\$ScreenshotTakenBannerKt\$lambda-1\$1;")) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
method.name == "invoke"
|
||||
}
|
||||
internal val BytecodePatchContext.disableScreenshotPopupMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("invoke")
|
||||
definingClass($$"$ScreenshotTakenBannerKt$lambda-1$1;"::endsWith)
|
||||
returnType("V")
|
||||
parameterTypes("Landroidx/compose/runtime/", "I")
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package app.revanced.patches.reddit.layout.premiumicon
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val hasPremiumIconAccessFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("MyAccount;") && method.name == "isPremiumSubscriber"
|
||||
}
|
||||
internal val BytecodePatchContext.hasPremiumIconAccessMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("isPremiumSubscriber")
|
||||
definingClass("MyAccount;"::endsWith)
|
||||
returnType("Z")
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package app.revanced.patches.reddit.layout.premiumicon
|
||||
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
val unlockPremiumIconsPatch = bytecodePatch(
|
||||
name = "Unlock Premium icons",
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Unlock Premium icons` by creatingBytecodePatch(
|
||||
description = "Unlocks the Reddit Premium icons.",
|
||||
) {
|
||||
compatibleWith("com.reddit.frontpage")
|
||||
|
||||
apply {
|
||||
hasPremiumIconAccessFingerprint.method.addInstructions(
|
||||
hasPremiumIconAccessMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package app.revanced.patches.reddit.misc.tracking.url
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.custom
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val shareLinkFormatterFingerprint = fingerprint {
|
||||
custom { _, classDef ->
|
||||
classDef.startsWith("Lcom/reddit/sharing/") && classDef.sourceFile == "UrlUtil.kt"
|
||||
}
|
||||
}
|
||||
internal val BytecodePatchContext.shareLinkFormatterMethod by gettingFirstMutableMethodDeclaratively {
|
||||
definingClass("Lcom/reddit/sharing/"::startsWith)
|
||||
custom { immutableClassDef.sourceFile == "UrlUtil.kt" }
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
||||
compatibleWith("com.reddit.frontpage")
|
||||
|
||||
apply {
|
||||
shareLinkFormatterFingerprint.method.addInstructions(
|
||||
0,
|
||||
"return-object p0",
|
||||
)
|
||||
shareLinkFormatterMethod.addInstructions(0, "return-object p0",)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.w3c.dom.Element
|
||||
|
||||
@Suppress("unused")
|
||||
internal val addManifestPermissionsPatch = resourcePatch {
|
||||
|
||||
val requiredPermissions = listOf(
|
||||
"android.permission.READ_PHONE_STATE",
|
||||
"android.permission.FOREGROUND_SERVICE_MICROPHONE",
|
||||
|
||||
@@ -5,7 +5,7 @@ package app.revanced.patches.samsung.radio.misc.fix.crash
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.samsung.radio.restrictions.device.bypassDeviceChecksPatch
|
||||
import app.revanced.patches.samsung.radio.restrictions.device.`Bypass device checks`
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -16,7 +16,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/samsung/
|
||||
val fixCrashPatch = bytecodePatch(
|
||||
name = "Fix crashes", description = "Prevents the app from crashing because of missing system permissions."
|
||||
) {
|
||||
dependsOn(addManifestPermissionsPatch, bypassDeviceChecksPatch)
|
||||
dependsOn(addManifestPermissionsPatch, `Bypass device checks`)
|
||||
extendWith("extensions/samsung/radio.rve")
|
||||
compatibleWith("com.sec.android.app.fm"("12.4.00.7", "12.3.00.13", "12.3.00.11"))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package app.revanced.patches.samsung.radio.restrictions.device
|
||||
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
@@ -12,9 +12,8 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/samsung/radio/restrictions/device/BypassDeviceChecksPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val bypassDeviceChecksPatch = bytecodePatch(
|
||||
name = "Bypass device checks",
|
||||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Bypass device checks` by creatingBytecodePatch(
|
||||
description = "Removes firmware and region blacklisting. " +
|
||||
"This patch will still not allow the app to run on devices that do not have the required hardware.",
|
||||
) {
|
||||
@@ -22,34 +21,33 @@ val bypassDeviceChecksPatch = bytecodePatch(
|
||||
compatibleWith("com.sec.android.app.fm"("12.4.00.7", "12.3.00.13", "12.3.00.11"))
|
||||
|
||||
apply {
|
||||
// Return false = The device is not blacklisted.
|
||||
checkDeviceFingerprint.method.apply {
|
||||
// Find the first string that start with "SM-", that's the list of incompatible devices.
|
||||
val firstStringIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.CONST_STRING &&
|
||||
getReference<StringReference>()?.string?.startsWith("SM-") == true
|
||||
}
|
||||
// Find the first string that start with "SM-", that's the list of incompatible devices.
|
||||
val firstStringIndex = checkDeviceMethod.indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.CONST_STRING &&
|
||||
getReference<StringReference>()?.string?.startsWith("SM-") == true
|
||||
}
|
||||
|
||||
// Find the following filled-new-array (or filled-new-array/range) instruction.
|
||||
val filledNewArrayIndex = indexOfFirstInstructionOrThrow(firstStringIndex + 1) {
|
||||
opcode == Opcode.FILLED_NEW_ARRAY || opcode == Opcode.FILLED_NEW_ARRAY_RANGE
|
||||
}
|
||||
// Find the following filled-new-array (or filled-new-array/range) instruction.
|
||||
val filledNewArrayIndex = checkDeviceMethod.indexOfFirstInstructionOrThrow(firstStringIndex + 1) {
|
||||
opcode == Opcode.FILLED_NEW_ARRAY || opcode == Opcode.FILLED_NEW_ARRAY_RANGE
|
||||
}
|
||||
|
||||
val resultRegister = findFreeRegister(filledNewArrayIndex + 1)
|
||||
val resultRegister = checkDeviceMethod.findFreeRegister(filledNewArrayIndex + 1)
|
||||
|
||||
// Store the array there and invoke the method that we added to the class earlier.
|
||||
addInstructions(
|
||||
filledNewArrayIndex + 1,
|
||||
"""
|
||||
// Store the array there and invoke the method that we added to the class earlier.
|
||||
checkDeviceMethod.addInstructions(
|
||||
filledNewArrayIndex + 1,
|
||||
"""
|
||||
move-result-object v$resultRegister
|
||||
invoke-static { v$resultRegister }, $EXTENSION_CLASS_DESCRIPTOR->checkIfDeviceIsIncompatible([Ljava/lang/String;)Z
|
||||
move-result v$resultRegister
|
||||
return v$resultRegister
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
// Remove the instructions before our strings.
|
||||
removeInstructions(0, firstStringIndex)
|
||||
}
|
||||
// Remove the instructions before our strings.
|
||||
// Return false = The device is not blacklisted.
|
||||
checkDeviceMethod.removeInstructions(0, firstStringIndex)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,61 +1,30 @@
|
||||
package app.revanced.patches.samsung.radio.restrictions.device
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||
import app.revanced.patches.all.misc.transformation.fromMethodReference
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
internal val checkDeviceFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
custom { method, _ ->
|
||||
/* Check for methods call to:
|
||||
- Landroid/os/SemSystemProperties;->getSalesCode()Ljava/lang/String;
|
||||
- Landroid/os/SemSystemProperties;->getCountryIso()Ljava/lang/String;
|
||||
*/
|
||||
|
||||
val impl = method.implementation ?: return@custom false
|
||||
|
||||
// Track which target methods we've found
|
||||
val foundMethods = mutableSetOf<MethodCall>()
|
||||
|
||||
// Scan method instructions for calls to our target methods
|
||||
for (instr in impl.instructions) {
|
||||
val ref = instr.getReference<MethodReference>() ?: continue
|
||||
val mc = fromMethodReference<MethodCall>(ref) ?: continue
|
||||
|
||||
if (mc == MethodCall.GetSalesCode || mc == MethodCall.GetCountryIso) {
|
||||
foundMethods.add(mc)
|
||||
|
||||
// If we found both methods, return success
|
||||
if (foundMethods.size == 2) {
|
||||
return@custom true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only match if both methods are present
|
||||
return@custom false
|
||||
}
|
||||
internal val BytecodePatchContext.checkDeviceMethod by gettingFirstMutableMethodDeclaratively {
|
||||
returnType("Z")
|
||||
instructions(
|
||||
predicates = unorderedAllOf(
|
||||
method { MethodUtil.methodSignaturesMatch(getSalesCodeMethodReference, this) },
|
||||
method { MethodUtil.methodSignaturesMatch(getCountryIsoMethodReference, this) }
|
||||
))
|
||||
}
|
||||
|
||||
// Information about method calls we want to replace
|
||||
private enum class MethodCall(
|
||||
override val definedClassName: String,
|
||||
override val methodName: String,
|
||||
override val methodParams: Array<String>,
|
||||
override val returnType: String,
|
||||
) : IMethodCall {
|
||||
GetSalesCode(
|
||||
"Landroid/os/SemSystemProperties;",
|
||||
"getSalesCode",
|
||||
arrayOf(),
|
||||
"Ljava/lang/String;",
|
||||
),
|
||||
GetCountryIso(
|
||||
"Landroid/os/SemSystemProperties;",
|
||||
"getCountryIso",
|
||||
arrayOf(),
|
||||
"Ljava/lang/String;",
|
||||
)
|
||||
}
|
||||
val getSalesCodeMethodReference = ImmutableMethodReference(
|
||||
"Landroid/os/SemSystemProperties;",
|
||||
"getSalesCode",
|
||||
emptyList(),
|
||||
"Ljava/lang/String;",
|
||||
)
|
||||
|
||||
val getCountryIsoMethodReference = ImmutableMethodReference(
|
||||
"Landroid/os/SemSystemProperties;",
|
||||
"getCountryIso",
|
||||
emptyList(),
|
||||
"Ljava/lang/String;",
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.shared
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val BytecodePatchContext.castContextFetchMethod by gettingFirstMutableMethodDeclaratively(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.shared.misc.checks
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.gettingFirstMutableClassDefDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableClassDefDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val BytecodePatchContext.patchInfoClassDef by gettingFirstMutableClassDefDeclaratively(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.debugging
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.ClassDefMethodMatching.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.extension
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.shared.misc.extension
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstMutableClassDef
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.firstMutableClassDef
|
||||
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
@@ -48,7 +48,7 @@ fun gmsCoreSupportPatch(
|
||||
fromPackageName: String,
|
||||
toPackageName: String,
|
||||
getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null,
|
||||
getEarlyReturnMethods: BytecodePatchContext.() -> Set<MutableMethod> = { setOf() },
|
||||
getEarlyReturnMethods: Set<BytecodePatchContext.() -> MutableMethod> = emptySet(),
|
||||
getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
|
||||
extensionPatch: Patch,
|
||||
gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option<String>) -> Patch,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.spoof
|
||||
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.method
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
@@ -8,8 +10,6 @@ import app.revanced.patcher.extensions.methodReference
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.method
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.spotify.shared
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.strava.mediaupload
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstClassDef
|
||||
import app.revanced.patcher.firstClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.intOption
|
||||
import app.revanced.patcher.patch.longOption
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.twitter.misc.hook.json
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.gettingFirstClassDef
|
||||
import app.revanced.patcher.ClassDefMethodMatching.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstClassDef
|
||||
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.twitter.misc.hook.json
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstClassDef
|
||||
import app.revanced.patcher.firstClassDef
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.gms
|
||||
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.castContextFetchMethod
|
||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.patches.shared.primeMethodFingerprint
|
||||
import app.revanced.patches.shared.primeMethod
|
||||
import app.revanced.patches.youtube.layout.buttons.overlay.hidePlayerOverlayButtonsPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.gms.Constants.REVANCED_YOUTUBE_PACKAGE_NAME
|
||||
@@ -13,16 +15,15 @@ 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.mainActivityOnCreateMethod
|
||||
|
||||
@Suppress("unused")
|
||||
val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
fromPackageName = YOUTUBE_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME,
|
||||
getPrimeMethod = primeMethodFingerprint,
|
||||
getEarlyReturnMethods = setOf(
|
||||
castContextFetchFingerprint,
|
||||
),
|
||||
getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint,
|
||||
getPrimeMethod = BytecodePatchContext::primeMethod::get,
|
||||
getEarlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get),
|
||||
getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get,
|
||||
extensionPatch = sharedExtensionPatch,
|
||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||
) {
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
package app.revanced.patches.youtube.shared
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.firstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.InstructionLocation.MatchAfterImmediately
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.literal
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.newInstance
|
||||
import app.revanced.patcher.opcode
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.after
|
||||
import app.revanced.patcher.allOf
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.field
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patcher.type
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||
import app.revanced.patches.shared.misc.mapping.resourceLiteral
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
@@ -126,18 +131,14 @@ internal val subtitleButtonControllerFingerprint = fingerprint {
|
||||
)
|
||||
}
|
||||
|
||||
internal val videoQualityChangedFingerprint = fingerprint {
|
||||
internal val videoQualityChangedMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
instructions(
|
||||
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).
|
||||
allOf(Opcode.NEW_INSTANCE(), type("Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;")),
|
||||
Opcode.IGET_OBJECT(),
|
||||
Opcode.CHECK_CAST(),
|
||||
after(allOf(Opcode.IGET(), field { type == "I" })) // Video resolution (human-readable).
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,58 +1,50 @@
|
||||
package app.revanced.patches.youtube.video.information
|
||||
|
||||
import app.revanced.patcher.InstructionLocation.MatchAfterWithin
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.literal
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedMethodMatch
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
|
||||
internal val createVideoPlayerSeekbarFingerprint = fingerprint {
|
||||
returns("V")
|
||||
instructions(
|
||||
addString("timed_markers_width"),
|
||||
)
|
||||
internal val BytecodePatchContext.createVideoPlayerSeekbarMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("V")
|
||||
instructions("timed_markers_width"())
|
||||
}
|
||||
|
||||
internal val onPlaybackSpeedItemClickFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.onPlaybackSpeedItemClickMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("onItemClick")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("L", "L", "I", "J")
|
||||
custom { method, _ ->
|
||||
method.name == "onItemClick" &&
|
||||
method.implementation?.instructions?.find {
|
||||
it.opcode == Opcode.IGET_OBJECT &&
|
||||
it.getReference<FieldReference>()!!.type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||
} != null
|
||||
}
|
||||
}
|
||||
|
||||
internal val playerControllerSetTimeReferenceFingerprint = fingerprint {
|
||||
opcodes(Opcode.INVOKE_DIRECT_RANGE, Opcode.IGET_OBJECT)
|
||||
strings("Media progress reported outside media playback: ")
|
||||
}
|
||||
|
||||
internal val playerInitFingerprint = fingerprint {
|
||||
returnType("V")
|
||||
parameterTypes("L", "L", "I", "J")
|
||||
instructions(
|
||||
addString("playVideo called on player response with no videoStreamingData."),
|
||||
allOf(
|
||||
Opcode.IGET_OBJECT(),
|
||||
field { type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" })
|
||||
)
|
||||
}
|
||||
|
||||
internal val playerControllerSetTimeReferenceMethodMatch =
|
||||
firstMethodComposite("Media progress reported outside media playback: ") {
|
||||
opcodes(
|
||||
Opcode.INVOKE_DIRECT_RANGE,
|
||||
Opcode.IGET_OBJECT
|
||||
)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.playVideoCheckVideoStreamingDataResponseMethod by gettingFirstMethodDeclaratively {
|
||||
instructions("playVideo called on player response with no videoStreamingData."())
|
||||
}
|
||||
|
||||
/**
|
||||
* Matched using class found in [playerInitFingerprint].
|
||||
* Matched using class found in [playVideoCheckVideoStreamingDataResponseMethod].
|
||||
*/
|
||||
internal val seekFingerprint = fingerprint {
|
||||
instructions(
|
||||
addString("Attempting to seek during an ad"),
|
||||
)
|
||||
internal fun ClassDef.getSeekMethod() = firstMethodDeclaratively {
|
||||
instructions("Attempting to seek during an ad"())
|
||||
}
|
||||
|
||||
internal val videoLengthFingerprint = fingerprint {
|
||||
internal val videoLengthMethodMatch = firstMethodComposite {
|
||||
opcodes(
|
||||
Opcode.MOVE_RESULT_WIDE,
|
||||
Opcode.CMP_LONG,
|
||||
@@ -70,38 +62,38 @@ internal val videoLengthFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches using class found in [mdxPlayerDirectorSetVideoStageFingerprint].
|
||||
* Matches using class found in [mdxPlayerDirectorSetVideoStageMethod].
|
||||
*/
|
||||
internal val mdxSeekFingerprint = fingerprint {
|
||||
context(_: BytecodePatchContext)
|
||||
internal fun ClassDef.getMdxSeekMethod() = firstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
parameters("J", "L")
|
||||
returnType("Z")
|
||||
parameterTypes("J", "L")
|
||||
opcodes(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.RETURN,
|
||||
)
|
||||
custom { methodDef, _ ->
|
||||
custom {
|
||||
// The instruction count is necessary here to avoid matching the relative version
|
||||
// of the seek method we're after, which has the same function signature as the
|
||||
// regular one, is in the same class, and even has the exact same 3 opcodes pattern.
|
||||
methodDef.implementation!!.instructions.count() == 3
|
||||
instructions.count() == 3
|
||||
}
|
||||
}
|
||||
|
||||
internal val mdxPlayerDirectorSetVideoStageFingerprint = fingerprint {
|
||||
instructions(
|
||||
addString("MdxDirector setVideoStage ad should be null when videoStage is not an Ad state "),
|
||||
)
|
||||
internal val BytecodePatchContext.mdxPlayerDirectorSetVideoStageMethod by gettingFirstMethodDeclaratively {
|
||||
instructions("MdxDirector setVideoStage ad should be null when videoStage is not an Ad state "())
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches using class found in [mdxPlayerDirectorSetVideoStageFingerprint].
|
||||
* Matches using class found in [mdxPlayerDirectorSetVideoStageMethod].
|
||||
*/
|
||||
internal val mdxSeekRelativeFingerprint = fingerprint {
|
||||
context(_: BytecodePatchContext)
|
||||
internal fun ClassDef.getMdxSeekRelativeMethod() = firstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
// Return type is boolean up to 19.39, and void with 19.39+.
|
||||
parameters("J", "L")
|
||||
parameterTypes("J", "L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
@@ -109,91 +101,85 @@ internal val mdxSeekRelativeFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches using class found in [playerInitFingerprint].
|
||||
* Matches using class found in [playVideoCheckVideoStreamingDataResponseMethod].
|
||||
*/
|
||||
internal val seekRelativeFingerprint = fingerprint {
|
||||
context(_: BytecodePatchContext)
|
||||
internal fun ClassDef.getSeekRelativeMethod() = firstMutableMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
// Return type is boolean up to 19.39, and void with 19.39+.
|
||||
parameters("J", "L")
|
||||
parameterTypes("J", "L")
|
||||
opcodes(
|
||||
Opcode.ADD_LONG_2ADDR,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
)
|
||||
}
|
||||
|
||||
internal val videoEndFingerprint = fingerprint {
|
||||
internal val videoEndMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
parameters("J", "L")
|
||||
returnType("Z")
|
||||
parameterTypes("J", "L")
|
||||
instructions(
|
||||
methodCall(
|
||||
parameters = listOf(),
|
||||
returnType = "V"
|
||||
),
|
||||
literal(45368273L, location = MatchAfterWithin(5)),
|
||||
addString("Attempting to seek when video is not playing"),
|
||||
method { parameterTypes.isEmpty() && returnType == "V" },
|
||||
afterAtMost(5, 45368273L()),
|
||||
"Attempting to seek when video is not playing"(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves with the class found in [videoQualityChangedFingerprint].
|
||||
* Matches with the class found in [videoQualityChangedMethodMatch].
|
||||
*/
|
||||
internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint {
|
||||
internal val playbackSpeedMenuSpeedChangedMethodMatch = firstMethodComposite {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
instructions(
|
||||
fieldAccess(opcode = Opcode.IGET, type = "F")
|
||||
)
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
instructions(allOf(Opcode.IGET(), field { type == "F" }))
|
||||
}
|
||||
|
||||
internal val playbackSpeedClassFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.playbackSpeedClassMethod by gettingFirstMutableMethodDeclaratively(
|
||||
"PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT"
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.RETURN_OBJECT
|
||||
)
|
||||
strings("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
opcodes(Opcode.RETURN_OBJECT)
|
||||
}
|
||||
|
||||
|
||||
internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
|
||||
internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE =
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
|
||||
|
||||
/**
|
||||
* YouTube 20.19 and lower.
|
||||
*/
|
||||
internal val videoQualityLegacyFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.videoQualityLegacyMethod by gettingFirstMutableMethodDeclaratively {
|
||||
definingClass(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE)
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters(
|
||||
parameterTypes(
|
||||
"I", // Resolution.
|
||||
"Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc
|
||||
"Z",
|
||||
"L"
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
internal val videoQualityFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.videoQualityMethod by gettingFirstMutableMethodDeclaratively {
|
||||
definingClass(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE)
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters(
|
||||
parameterTypes(
|
||||
"I", // Resolution.
|
||||
"L",
|
||||
"Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc
|
||||
"Z",
|
||||
"L"
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
internal val videoQualitySetterFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.videoQualitySetterMethod by gettingFirstMutableMethodDeclaratively(
|
||||
"menu_item_video_quality"
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("[L", "I", "Z")
|
||||
returnType("V")
|
||||
parameterTypes("[L", "I", "Z")
|
||||
opcodes(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
@@ -201,15 +187,15 @@ internal val videoQualitySetterFingerprint = fingerprint {
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
)
|
||||
strings("menu_item_video_quality")
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches with the class found in [videoQualitySetterFingerprint].
|
||||
* Matches with the class found in [videoQualitySetterMethod].
|
||||
*/
|
||||
internal val setVideoQualityFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("L")
|
||||
context(_: BytecodePatchContext)
|
||||
internal fun ClassDef.getSetVideoQualityMethod() = firstMutableMethodDeclaratively {
|
||||
returnType("V")
|
||||
parameterTypes("L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
package app.revanced.patches.youtube.video.information
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstMutableClassDef
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableClassDef
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.*
|
||||
import app.revanced.patcher.firstMutableClassDef
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_20_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedMethodMatch
|
||||
import app.revanced.patches.youtube.video.playerresponse.Hook
|
||||
import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook
|
||||
import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch
|
||||
@@ -37,6 +34,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableClassDef
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/VideoInformation;"
|
||||
@@ -91,27 +91,26 @@ val videoInformationPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
apply {
|
||||
playerInitMethod = playerInitFingerprint.classDef.methods.first { MethodUtil.isConstructor(it) }
|
||||
with(playVideoCheckVideoStreamingDataResponseMethod) {
|
||||
playerInitMethod = classDef.methods.first { MethodUtil.isConstructor(it) }
|
||||
|
||||
// Find the location of the first invoke-direct call and extract the register storing the 'this' object reference.
|
||||
val initThisIndex = playerInitMethod.indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
|
||||
// Find the location of the first invoke-direct call
|
||||
// and extract the register storing the 'this' object reference.
|
||||
val initThisIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
|
||||
}
|
||||
playerInitInsertRegister = getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
|
||||
playerInitInsertIndex = initThisIndex + 1
|
||||
|
||||
// Create extension interface methods.
|
||||
addSeekInterfaceMethods(
|
||||
playVideoCheckVideoStreamingDataResponseMethod.classDef,
|
||||
classDef.getSeekMethod(),
|
||||
classDef.getSeekRelativeMethod()
|
||||
)
|
||||
}
|
||||
playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
|
||||
playerInitInsertIndex = initThisIndex + 1
|
||||
|
||||
val seekFingerprintResultMethod = seekFingerprint.match(playerInitFingerprint.originalClassDef).method
|
||||
val seekRelativeFingerprintResultMethod =
|
||||
seekRelativeFingerprint.match(playerInitFingerprint.originalClassDef).method
|
||||
|
||||
// Create extension interface methods.
|
||||
addSeekInterfaceMethods(
|
||||
playerInitFingerprint.classDef,
|
||||
seekFingerprintResultMethod,
|
||||
seekRelativeFingerprintResultMethod,
|
||||
)
|
||||
|
||||
with(mdxPlayerDirectorSetVideoStageFingerprint) {
|
||||
with(mdxPlayerDirectorSetVideoStageMethod) {
|
||||
mdxInitMethod = classDef.methods.first { MethodUtil.isConstructor(it) }
|
||||
|
||||
val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow {
|
||||
@@ -123,31 +122,31 @@ val videoInformationPatch = bytecodePatch(
|
||||
// Hook the MDX director for use through the extension.
|
||||
onCreateHookMdx(EXTENSION_CLASS_DESCRIPTOR, "initializeMdx")
|
||||
|
||||
val mdxSeekFingerprintResultMethod = mdxSeekFingerprint.match(classDef).method
|
||||
val mdxSeekRelativeFingerprintResultMethod = mdxSeekRelativeFingerprint.match(classDef).method
|
||||
|
||||
addSeekInterfaceMethods(classDef, mdxSeekFingerprintResultMethod, mdxSeekRelativeFingerprintResultMethod)
|
||||
addSeekInterfaceMethods(
|
||||
classDef,
|
||||
classDef.getMdxSeekMethod(),
|
||||
classDef.getMdxSeekRelativeMethod()
|
||||
)
|
||||
}
|
||||
|
||||
with(createVideoPlayerSeekbarFingerprint) {
|
||||
val videoLengthMethodMatch = videoLengthFingerprint.match(originalClassDef)
|
||||
with(createVideoPlayerSeekbarMethod) {
|
||||
val videoLengthMethodMatch = videoLengthMethodMatch.match(immutableClassDef)
|
||||
|
||||
videoLengthMethodMatch.method.apply {
|
||||
val videoLengthRegisterIndex = videoLengthMethodMatch.instructionMatches.last().index - 2
|
||||
val videoLengthRegisterIndex = videoLengthMethodMatch.indices.last()
|
||||
val videoLengthRegister = getInstruction<OneRegisterInstruction>(videoLengthRegisterIndex).registerA
|
||||
val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide
|
||||
|
||||
addInstruction(
|
||||
videoLengthMethodMatch.instructionMatches.last().index,
|
||||
videoLengthMethodMatch.indices.last(),
|
||||
"invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->setVideoLength(J)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
videoEndFingerprint.let {
|
||||
videoEndMethod = navigate(it.originalMethod).to(it.instructionMatches[0].index).stop()
|
||||
}
|
||||
videoEndMethod = navigate(videoEndMethodMatch.immutableMethod)
|
||||
.to(videoEndMethodMatch.indices.first()).stop()
|
||||
|
||||
/*
|
||||
* Inject call for video ids
|
||||
@@ -170,9 +169,8 @@ val videoInformationPatch = bytecodePatch(
|
||||
/*
|
||||
* Set the video time method
|
||||
*/
|
||||
timeMethod = navigate(playerControllerSetTimeReferenceFingerprint.originalMethod)
|
||||
.to(playerControllerSetTimeReferenceFingerprint.instructionMatches.first().index)
|
||||
.stop()
|
||||
timeMethod = navigate(playerControllerSetTimeReferenceMethodMatch.immutableMethod)
|
||||
.to(playerControllerSetTimeReferenceMethodMatch.indices.first()).stop()
|
||||
|
||||
/*
|
||||
* Hook the methods which set the time
|
||||
@@ -182,7 +180,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
/*
|
||||
* Hook the user playback speed selection.
|
||||
*/
|
||||
onPlaybackSpeedItemClickFingerprint.method.apply {
|
||||
onPlaybackSpeedItemClickMethod.apply {
|
||||
val speedSelectionValueInstructionIndex = indexOfFirstInstructionOrThrow(Opcode.IGET)
|
||||
|
||||
legacySpeedSelectionInsertMethod = this
|
||||
@@ -203,7 +201,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
setPlaybackSpeedMethodIndex = 0
|
||||
|
||||
// Add override playback speed method.
|
||||
onPlaybackSpeedItemClickFingerprint.classDef.methods.add(
|
||||
onPlaybackSpeedItemClickMethod.classDef.methods.add(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
"overridePlaybackSpeed",
|
||||
@@ -240,7 +238,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
playbackSpeedClassFingerprint.method.apply {
|
||||
playbackSpeedClassMethod.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
val playbackSpeedClass = this.returnType
|
||||
@@ -270,11 +268,9 @@ val videoInformationPatch = bytecodePatch(
|
||||
}
|
||||
|
||||
// Handle new playback speed menu.
|
||||
playbackSpeedMenuSpeedChangedFingerprint.match(
|
||||
videoQualityChangedFingerprint.originalClassDef,
|
||||
).let {
|
||||
playbackSpeedMenuSpeedChangedMethodMatch.match(videoQualityChangedMethodMatch.immutableClassDef).let {
|
||||
it.method.apply {
|
||||
val index = it.instructionMatches.first().index
|
||||
val index = it.indices.first()
|
||||
|
||||
speedSelectionInsertMethod = this
|
||||
speedSelectionInsertIndex = index + 1
|
||||
@@ -282,10 +278,10 @@ val videoInformationPatch = bytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
(if (is_20_19_or_greater) videoQualityFingerprint else videoQualityLegacyFingerprint).let {
|
||||
(if (is_20_19_or_greater) videoQualityMethod else videoQualityLegacyMethod).apply {
|
||||
// Fix bad data used by YouTube.
|
||||
val nameRegister = if (is_20_20_or_greater) "p3" else "p2"
|
||||
it.method.addInstructions(
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { $nameRegister, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I
|
||||
@@ -294,7 +290,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
// Add methods to access obfuscated quality fields.
|
||||
it.classDef.apply {
|
||||
classDef.apply {
|
||||
methods.add(
|
||||
ImmutableMethod(
|
||||
type,
|
||||
@@ -349,16 +345,13 @@ val videoInformationPatch = bytecodePatch(
|
||||
}
|
||||
|
||||
// Detect video quality changes and override the current quality.
|
||||
setVideoQualityFingerprint.match(
|
||||
videoQualitySetterFingerprint.originalClassDef
|
||||
).let { match ->
|
||||
videoQualitySetterMethod.immutableClassDef.getSetVideoQualityMethod().let {
|
||||
it
|
||||
// This instruction refers to the field with the type that contains the setQuality method.
|
||||
val onItemClickListenerClassReference = match.method
|
||||
.getInstruction<ReferenceInstruction>(0).reference
|
||||
val setQualityFieldReference = match.method
|
||||
.getInstruction<ReferenceInstruction>(1).reference as FieldReference
|
||||
val onItemClickListenerClassReference = it.getInstruction<ReferenceInstruction>(0).reference
|
||||
val setQualityFieldReference = it.getInstruction<ReferenceInstruction>(1).fieldReference!!
|
||||
|
||||
firstClassDefMutable(setQualityFieldReference.type).apply {
|
||||
firstMutableClassDef(setQualityFieldReference.type).apply {
|
||||
// Add interface and helper methods to allow extension code to call obfuscated methods.
|
||||
interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE)
|
||||
|
||||
@@ -390,7 +383,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
videoQualitySetterFingerprint.method.addInstructions(
|
||||
videoQualitySetterMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Get object instance to invoke setQuality method.
|
||||
|
||||
@@ -9,10 +9,9 @@ import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_20_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedMethodMatch
|
||||
import app.revanced.patches.youtube.video.information.onCreateHook
|
||||
import app.revanced.patches.youtube.video.information.videoInformationPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
@@ -33,32 +32,34 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
apply {
|
||||
addResources("youtube", "video.quality.rememberVideoQualityPatch")
|
||||
|
||||
settingsMenuVideoQualityGroup.addAll(listOf(
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_mobile",
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_wifi",
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected"),
|
||||
settingsMenuVideoQualityGroup.addAll(
|
||||
listOf(
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_mobile",
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_wifi",
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected"),
|
||||
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_mobile",
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_wifi",
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected"),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected_toast")
|
||||
))
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_mobile",
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_wifi",
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected"),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected_toast")
|
||||
)
|
||||
)
|
||||
|
||||
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
|
||||
|
||||
@@ -71,14 +72,13 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
)
|
||||
|
||||
// Inject a call to remember the user selected quality for regular videos.
|
||||
videoQualityChangedFingerprint.method.apply {
|
||||
val index = videoQualityChangedFingerprint.instructionMatches[3].index
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
videoQualityChangedMethodMatch.let { match ->
|
||||
val index = match.indices[3]
|
||||
val register = match.method.getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstruction(
|
||||
match.method.addInstruction(
|
||||
index + 1,
|
||||
"invoke-static { v$register }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.util
|
||||
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstMutableClassDef
|
||||
import app.revanced.patcher.BytecodePatchContextClassDefMatching.firstMutableClassDefOrNull
|
||||
import app.revanced.patcher.firstMutableClassDef
|
||||
import app.revanced.patcher.firstMutableClassDefOrNull
|
||||
import app.revanced.patcher.FingerprintBuilder
|
||||
import app.revanced.patcher.extensions.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
Reference in New Issue
Block a user