Merge remote-tracking branch 'upstream/dev' into chore/lint

# Conflicts:
#	api/revanced-patches.api
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckTwoFingerprint.kt
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/MediaFingerprint.kt
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt
#	src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/ShoppingAdFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt
#	src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt
#	src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt
#	src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt
#	src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt
#	src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/DisablePreciseSeekingGesturePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/DisableFullscreenAmbientModePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/InitializeButtonsFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt
This commit is contained in:
LisoUseInAIKyrios
2024-03-30 20:34:34 +04:00
132 changed files with 2229 additions and 1538 deletions

View File

@@ -3,102 +3,61 @@ package app.revanced.patches.instagram.patches.ads.timeline
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckOneFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckTwoFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.GenericMediaAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide timeline ads",
description = "Removes ads from the timeline.",
compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])],
compatiblePackages = [CompatiblePackage("com.instagram.android")],
)
@Suppress("unused")
object HideTimelineAdsPatch : BytecodePatch(
setOf(
ShowAdFingerprint,
MediaFingerprint,
// Unlike the other ads this one is resolved from all classes.
PaidPartnershipAdFingerprint,
IsAdCheckOneFingerprint,
IsAdCheckTwoFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
// region Resolve required methods to check for ads.
// The exact function of the following methods is unknown.
// They are used to check if a post is an ad.
val isAdCheckOneMethod = IsAdCheckOneFingerprint.result?.method ?: throw IsAdCheckOneFingerprint.exception
val isAdCheckTwoMethod = IsAdCheckTwoFingerprint.result?.method ?: throw IsAdCheckTwoFingerprint.exception
ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception
ShowAdFingerprint.result?.let {
it.mutableMethod.apply {
// The register that holds the post object.
val postRegister = getInstruction<FiveRegisterInstruction>(1).registerC
PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception
// At this index the check for an ad can be performed.
val checkIndex = it.scanResult.patternScanResult!!.endIndex
MediaFingerprint.result?.let {
GenericMediaAdFingerprint.resolve(context, it.classDef)
ShoppingAdFingerprint.resolve(context, it.classDef)
return@let
} ?: throw MediaFingerprint.exception
// endregion
ShowAdFingerprint.result!!.apply {
// region Create instructions.
val scanStart = scanResult.patternScanResult!!.startIndex
val jumpIndex = scanStart - 1
val mediaInstanceRegister = mutableMethod.getInstruction<FiveRegisterInstruction>(scanStart).registerC
val freeRegister = mutableMethod.getInstruction<OneRegisterInstruction>(jumpIndex).registerA
val returnFalseLabel = "an_ad"
val checkForAdInstructions =
listOf(GenericMediaAdFingerprint, PaidPartnershipAdFingerprint, ShoppingAdFingerprint)
.map(MediaAdFingerprint::toString)
.joinToString("\n") {
"""
invoke-virtual {v$mediaInstanceRegister}, $it
move-result v$freeRegister
if-nez v$freeRegister, :$returnFalseLabel
""".trimIndent()
}.let { "$it\nconst/4 v0, 0x1\nreturn v0" }
// endregion
// region Patch.
val insertIndex = scanStart + 3
mutableMethod.addInstructionsWithLabels(
insertIndex,
checkForAdInstructions,
ExternalLabel(
returnFalseLabel,
// return false = ad
mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2),
),
)
// endregion
// region Jump to checks for ads from previous patch.
mutableMethod.apply {
// If either check returns true, the post is an ad and is hidden by returning false.
addInstructionsWithLabels(
jumpIndex + 1,
"if-nez v$freeRegister, :start_check",
ExternalLabel("start_check", getInstruction(insertIndex)),
checkIndex,
"""
invoke-virtual { v$postRegister }, $isAdCheckOneMethod
move-result v0
if-nez v0, :hide_ad
invoke-static { v$postRegister }, $isAdCheckTwoMethod
move-result v0
if-eqz v0, :not_an_ad
:hide_ad
const/4 v0, 0x0 # Returning false to hide the ad.
return v0
""",
ExternalLabel("not_an_ad", getInstruction(checkIndex)),
)
}.removeInstruction(jumpIndex)
// endregion
}
}
} ?: throw ShowAdFingerprint.exception
}
}

View File

@@ -0,0 +1,18 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object IsAdCheckOneFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
opcodes = listOf(
Opcode.XOR_INT_LIT8,
Opcode.IF_NE,
Opcode.RETURN,
Opcode.INVOKE_VIRTUAL,
),
)

View File

@@ -1,8 +1,14 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object GenericMediaAdFingerprint : MediaAdFingerprint(
internal object IsAdCheckTwoFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
@@ -13,6 +19,4 @@ internal object GenericMediaAdFingerprint : MediaAdFingerprint(
Opcode.CONST_4,
Opcode.RETURN,
),
) {
override fun toString() = result!!.method.toString()
}
)

View File

@@ -1,7 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object MediaFingerprint : MethodFingerprint(
strings = listOf("force_overlay", "Media#updateFields", "live_reels_metadata"),
)

View File

@@ -10,16 +10,12 @@ internal object ShowAdFingerprint : MethodFingerprint(
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
listOf("L", "L", "Z", "Z"),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.IF_NE,
Opcode.IF_NEZ,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.RETURN,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
),
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
internal abstract class MediaAdFingerprint(
returnType: String? = "Z",
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable<String>? = listOf(),
opcodes: Iterable<Opcode>?,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
) : MethodFingerprint(
returnType,
accessFlags,
parameters,
opcodes,
customFingerprint = customFingerprint,
) {
abstract override fun toString(): String
}

View File

@@ -1,29 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object PaidPartnershipAdFingerprint : MediaAdFingerprint(
"V",
null,
listOf("L", "L"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IPUT_BOOLEAN,
Opcode.IPUT_BOOLEAN,
),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("ClipsEditMetadataController;")
},
) {
override fun toString() = result!!.let {
val adCheckIndex = it.scanResult.patternScanResult!!.startIndex
val adCheckInstruction = it.method.implementation!!.instructions.elementAt(adCheckIndex)
val adCheckMethod = (adCheckInstruction as ReferenceInstruction).reference as MethodReference
adCheckMethod.toString()
}
}

View File

@@ -1,21 +0,0 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode
internal object ShoppingAdFingerprint : MediaAdFingerprint(
opcodes = listOf(
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.XOR_INT_LIT8,
Opcode.IF_EQZ,
),
) {
override fun toString() = result!!.method.toString()
}

View File

@@ -0,0 +1,39 @@
package app.revanced.patches.mifitness.misc.locale
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.mifitness.misc.locale.fingerprints.SyncBluetoothLanguageFingerprint
import app.revanced.patches.mifitness.misc.login.FixLoginPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Force English locale",
description = "Forces wearable devices to use the English locale.",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
dependencies = [FixLoginPatch::class],
)
@Suppress("unused")
object ForceEnglishLocalePatch : BytecodePatch(
setOf(SyncBluetoothLanguageFingerprint),
) {
override fun execute(context: BytecodeContext) {
SyncBluetoothLanguageFingerprint.result?.let {
val resolvePhoneLocaleInstruction = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val registerIndexToUpdate =
getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA
replaceInstruction(
resolvePhoneLocaleInstruction,
"const-string v$registerIndexToUpdate, \"en_gb\"",
)
}
} ?: throw SyncBluetoothLanguageFingerprint.exception
}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.mifitness.misc.locale.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object SyncBluetoothLanguageFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" &&
methodDef.name == "syncBluetoothLanguage"
},
opcodes = listOf(Opcode.MOVE_RESULT_OBJECT),
)

View File

@@ -0,0 +1,35 @@
package app.revanced.patches.mifitness.misc.login
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Fix login",
description = "Fixes login for uncertified Mi Fitness app",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
)
@Suppress("unused")
object FixLoginPatch : BytecodePatch(
setOf(XiaomiAccountManagerConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
XiaomiAccountManagerConstructorFingerprint.result?.let {
it.mutableMethod.apply {
val isCertifiedIndex = it.scanResult.patternScanResult!!.startIndex
val isCertifiedRegister = getInstruction<OneRegisterInstruction>(isCertifiedIndex).registerA
addInstruction(
isCertifiedIndex,
"const/4 p$isCertifiedRegister, 0x0",
)
}
} ?: throw XiaomiAccountManagerConstructorFingerprint.exception
}
}

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.mifitness.misc.login.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
},
opcodes = listOf(Opcode.IF_NEZ),
)

View File

@@ -0,0 +1,37 @@
package app.revanced.patches.music.ad.video
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint
import app.revanced.util.exception
@Patch(
name = "Hide music video ads",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object HideMusicVideoAds : BytecodePatch(
setOf(ShowMusicVideoAdsParentFingerprint),
) {
override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsParentFingerprint.result?.let {
val showMusicVideoAdsMethod = context
.toMethodWalker(it.mutableMethod)
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod
showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
} ?: throw ShowMusicVideoAdsParentFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to HideMusicVideoAds.")
object MusicVideoAdsPatch : BytecodePatch(
dependencies = setOf(HideMusicVideoAds::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,32 +0,0 @@
package app.revanced.patches.music.ad.video
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
@Patch(
name = "Music video ads",
description = "Removes ads in the music player.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object MusicVideoAdsPatch : BytecodePatch(
setOf(ShowMusicVideoAdsConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
val result = ShowMusicVideoAdsFingerprint.result!!
result.mutableMethod.addInstruction(
result.scanResult.patternScanResult!!.startIndex,
"""
const/4 p1, 0x0
""",
)
}
}

View File

@@ -1,30 +0,0 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST_4,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID,
),
)

View File

@@ -1,17 +0,0 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("Z"),
listOf(
Opcode.IPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID,
),
)

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
),
strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."),
)

View File

@@ -10,11 +10,10 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin
import com.android.tools.smali.dexlib2.Opcode
@Patch(
name = "Codecs unlock",
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
@Deprecated("This patch is no longer needed as the feature is now enabled by default.")
object CodecsUnlockPatch : BytecodePatch(
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint),
) {

View File

@@ -9,12 +9,12 @@ import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AllowExclusi
import app.revanced.util.exception
@Patch(
name = "Exclusive audio playback",
name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object ExclusiveAudioPatch : BytecodePatch(
object EnableExclusiveAudioPlayback : BytecodePatch(
setOf(AllowExclusiveAudioPlaybackFingerprint),
) {
override fun execute(context: BytecodeContext) {
@@ -29,3 +29,8 @@ object ExclusiveAudioPatch : BytecodePatch(
} ?: throw AllowExclusiveAudioPlaybackFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to EnableExclusiveAudioPlayback.")
object ExclusiveAudioPatch : BytecodePatch(emptySet()) {
override fun execute(context: BytecodeContext) = EnableExclusiveAudioPlayback.execute(context)
}

View File

@@ -22,3 +22,11 @@ object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
?: throw DisableShuffleFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to PermanentShufflePatch.")
object PermanentShuffleTogglePatch : BytecodePatch(
dependencies = setOf(PermanentShufflePatch::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,35 +0,0 @@
package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x
@Patch(
name = "Compact header",
description = "Hides the music category bar at the top of the homepage.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false,
)
@Suppress("unused")
object CompactHeaderPatch : BytecodePatch(
setOf(CompactHeaderConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
val result = CompactHeaderConstructorFingerprint.result!!
val method = result.mutableMethod
val insertIndex = result.scanResult.patternScanResult!!.endIndex
val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
method.addInstructions(
insertIndex,
"""
const/16 v2, 0x8
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V
""",
)
}
}

View File

@@ -0,0 +1,47 @@
package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.compactheader.fingerprints.ConstructCategoryBarFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Hide category bar",
description = "Hides the category bar at the top of the homepage.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false,
)
@Suppress("unused")
object HideCategoryBar : BytecodePatch(
setOf(ConstructCategoryBarFingerprint),
) {
override fun execute(context: BytecodeContext) {
ConstructCategoryBarFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions(
insertIndex,
"""
const/16 v2, 0x8
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V
""",
)
}
} ?: throw ConstructCategoryBarFingerprint.exception
}
}
@Deprecated("This patch class has been renamed to HideCategoryBar.")
object CompactHeaderPatch : BytecodePatch(
dependencies = setOf(HideCategoryBar::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -5,22 +5,19 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CompactHeaderConstructorFingerprint : MethodFingerprint(
internal object ConstructCategoryBarFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "L", "L", "L", "L"),
listOf("Landroid/content/Context;", "L", "L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
),
)

View File

@@ -2,24 +2,38 @@ package app.revanced.patches.music.layout.minimizedplayback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
import app.revanced.util.exception
@Patch(
name = "Minimized playback music",
description = "Enables minimized playback on Kids music.",
name = "Minimized playback",
description = "Unlocks options for picture-in-picture and background playback.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) {
override fun execute(context: BytecodeContext) =
MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction(
object MinimizedPlaybackPatch : BytecodePatch(
setOf(
KidsMinimizedPlaybackPolicyControllerFingerprint,
BackgroundPlaybackDisableFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction(
0,
"return-void",
) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
return-void
const/4 v0, 0x1
return v0
""",
) ?: throw MinimizedPlaybackManagerFingerprint.exception
) ?: throw BackgroundPlaybackDisableFingerprint.exception
}
}

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),
listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
),
)

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("I", "L", "Z"),

View File

@@ -2,41 +2,44 @@ package app.revanced.patches.music.layout.premium
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Hide get premium",
description = "Removes all \"Get Premium\" evidences from the avatar menu.",
name = "Hide 'Get Music Premium' label",
description = "Hides the red \"Get Music Premium\" label from the account menu.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) {
object HideGetPremiumPatch : BytecodePatch(
setOf(HideGetPremiumFingerprint),
) {
override fun execute(context: BytecodeContext) {
val parentResult = HideGetPremiumParentFingerprint.result!!
HideGetPremiumFingerprint.resolve(context, parentResult.classDef)
HideGetPremiumFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val startIndex = parentResult.scanResult.patternScanResult!!.startIndex
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(insertIndex)
val getPremiumViewRegister = setVisibilityInstruction.registerC
val visibilityRegister = setVisibilityInstruction.registerD
val parentMethod = parentResult.mutableMethod
parentMethod.replaceInstruction(
startIndex,
"""
const/4 v1, 0x0
""",
)
replaceInstruction(
insertIndex,
"const/16 v$visibilityRegister, 0x8",
)
val result = HideGetPremiumFingerprint.result!!
val method = result.mutableMethod
method.addInstruction(
startIndex,
"""
const/16 v0, 0x8
""",
)
addInstruction(
insertIndex + 1,
"invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " +
"Landroid/view/View;->setVisibility(I)V",
)
}
} ?: throw HideGetPremiumFingerprint.exception
}
}

View File

@@ -12,8 +12,7 @@ internal object HideGetPremiumFingerprint : MethodFingerprint(
listOf(
Opcode.IF_NEZ,
Opcode.CONST_16,
Opcode.GOTO,
Opcode.NOP,
Opcode.INVOKE_VIRTUAL,
),
listOf("FEmusic_history", "FEmusic_offline"),
)

View File

@@ -1,22 +0,0 @@
package app.revanced.patches.music.layout.premium.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object HideGetPremiumParentFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
listOf(
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
),
listOf("FEmusic_history"),
)

View File

@@ -1,16 +1,23 @@
package app.revanced.patches.music.layout.upgradebutton
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.newLabel
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch(
name = "Remove upgrade button",
@@ -22,54 +29,56 @@ object RemoveUpgradeButtonPatch : BytecodePatch(
setOf(PivotBarConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
val result = PivotBarConstructorFingerprint.result!!
val implementation = result.mutableMethod.implementation!!
PivotBarConstructorFingerprint.result?.let {
it.mutableMethod.apply {
val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1)
.getReference<FieldReference>()
val pivotBarElementFieldRef =
(implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference
val register = (getInstructions().first() as Instruction35c).registerC
val register = (implementation.instructions.first() as Instruction35c).registerC
// first compile all the needed instructions
val instructionList = """
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x4
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, v$register, $pivotBarElementFieldRef
""".toInstructions().toMutableList()
// First compile all the needed instructions.
val instructionList = """
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x4
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, v$register, $pivotBarElementFieldReference
""".toInstructions().toMutableList()
val endIndex = result.scanResult.patternScanResult!!.endIndex
val endIndex = it.scanResult.patternScanResult!!.endIndex
// replace the instruction to retain the label at given index
implementation.replaceInstruction(
endIndex - 1,
instructionList[0], // invoke-interface
)
// do not forget to remove this instruction since we added it already
instructionList.removeFirst()
// Replace the instruction to retain the label at given index.
replaceInstruction(
endIndex - 1,
instructionList[0], // invoke-interface.
)
// Do not forget to remove this instruction since we added it already.
instructionList.removeFirst()
val exitInstruction = instructionList.last() // iput-object
implementation.addInstruction(
endIndex,
exitInstruction,
)
// do not forget to remove this instruction since we added it already
instructionList.removeLast()
val exitInstruction = instructionList.last() // iput-object
addInstruction(
endIndex,
exitInstruction,
)
// Do not forget to remove this instruction since we added it already.
instructionList.removeLast()
// add the necessary if statement to remove the upgrade tab button in case it exists
instructionList.add(
2, // if-le
BuilderInstruction22t(
Opcode.IF_LE,
1,
2,
implementation.newLabelForIndex(endIndex),
),
)
// Add the necessary if statement to remove the upgrade tab button in case it exists.
instructionList.add(
2, // if-le.
BuilderInstruction22t(
Opcode.IF_LE,
1,
2,
newLabel(endIndex),
),
)
implementation.addInstructions(
endIndex,
instructionList,
)
addInstructions(
endIndex,
instructionList,
)
}
} ?: throw PivotBarConstructorFingerprint.exception
}
}

View File

@@ -2,59 +2,17 @@ package app.revanced.patches.music.layout.upgradebutton.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object PivotBarConstructorFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.NOP,
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID,
),

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.music.misc.gms
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
import app.revanced.patches.music.misc.gms.fingerprints.*
import app.revanced.patches.music.misc.integrations.IntegrationsPatch
import app.revanced.patches.music.misc.integrations.fingerprints.ApplicationInitFingerprint
@@ -34,5 +34,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
PrimeMethodFingerprint,
),
) {
override val gmsCoreVendor by gmsCoreVendorOption
override val gmsCoreVendor by gmsCoreVendorGroupIdOption
}

View File

@@ -1,26 +1,12 @@
package app.revanced.patches.music.premium.backgroundplay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
import app.revanced.util.exception
@Patch(
name = "Background play",
description = "Enables playing music in the background.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
)
@Suppress("unused")
object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) {
override fun execute(context: BytecodeContext) =
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""",
) ?: throw BackgroundPlaybackDisableFingerprint.exception
import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch
@Deprecated("This patch has been merged into MinimizedPlaybackPatch.")
object BackgroundPlayPatch : BytecodePatch(
dependencies = setOf(MinimizedPlaybackPatch::class),
) {
override fun execute(context: BytecodeContext) {
}
}

View File

@@ -1,45 +0,0 @@
package app.revanced.patches.music.premium.backgroundplay.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),
listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN,
Opcode.RETURN,
),
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.reddit.customclients.ads
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.reddit.customclients.ads.fingerprints.IsAdsEnabledFingerprint
import app.revanced.util.returnEarly
abstract class BaseDisableAdsPatch(
dependencies: Set<PatchClass> = emptySet(),
compatiblePackages: Set<CompatiblePackage>,
) : BytecodePatch(
name = "Disable ads",
dependencies = dependencies,
compatiblePackages = compatiblePackages,
fingerprints = setOf(IsAdsEnabledFingerprint),
) {
override fun execute(context: BytecodeContext) = listOf(IsAdsEnabledFingerprint).returnEarly()
}

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints
package app.revanced.patches.reddit.customclients.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforlemmy.ads
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
@Suppress("unused")
object DisableAdsPatch : BaseDisableAdsPatch(
dependencies = setOf(DisablePiracyDetectionPatch::class),
compatiblePackages = setOf(CompatiblePackage("com.laurencedawson.reddit_sync")),
)

View File

@@ -1,30 +1,8 @@
package app.revanced.patches.reddit.customclients.syncforreddit.ads
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
import app.revanced.util.exception
import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch
@Patch(
name = "Disable ads",
dependencies = [DisablePiracyDetectionPatch::class],
compatiblePackages = [CompatiblePackage("com.laurencedawson.reddit_sync")],
)
@Suppress("unused")
object DisableAdsPatch : BytecodePatch(setOf(IsAdsEnabledFingerprint)) {
override fun execute(context: BytecodeContext) {
IsAdsEnabledFingerprint.result?.mutableMethod?.apply {
addInstructions(
0,
"""
const/4 v0, 0x0
return v0
""",
)
} ?: throw IsAdsEnabledFingerprint.exception
}
}
object DisableAdsPatch : BaseDisableAdsPatch(
compatiblePackages = setOf(CompatiblePackage("io.syncapps.lemmy_sync")),
)

View File

@@ -96,7 +96,7 @@ abstract class BaseGmsCoreSupportPatch(
// Check the availability of GmsCore.
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction(
1, // Hack to not disturb other patches (such as the integrations patch).
"invoke-static {}, Lapp/revanced/integrations/youtube/patches/GmsCoreSupport;->checkAvailability()V",
"invoke-static {}, Lapp/revanced/integrations/shared/GmsCoreSupport;->checkAvailability()V",
) ?: throw mainActivityOnCreateFingerprint.exception
// Change the vendor of GmsCore in ReVanced Integrations.
@@ -274,6 +274,9 @@ abstract class BaseGmsCoreSupportPatch(
// fido
"com.google.android.gms.fido.fido2.privileged.START",
// gass
"com.google.android.gms.gass.START",
// games
"com.google.android.gms.games.service.START",
"com.google.android.gms.games.PLAY_GAMES_UPGRADE",
@@ -293,8 +296,18 @@ abstract class BaseGmsCoreSupportPatch(
// misc
"com.google.android.gms.gmscompliance.service.START",
"com.google.android.gms.oss.licenses.service.START",
"com.google.android.gms.safetynet.service.START",
"com.google.android.gms.tapandpay.service.BIND",
"com.google.android.gms.measurement.START",
"com.google.android.gms.languageprofile.service.START",
"com.google.android.gms.clearcut.service.START",
"com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE",
// potoken
"com.google.android.gms.potokens.service.START",
// droidguard/ safetynet
"com.google.android.gms.droidguard.service.START",
"com.google.android.gms.safetynet.service.START",
)
/**

View File

@@ -24,21 +24,23 @@ abstract class BaseGmsCoreSupportResourcePatch(
private val spoofedPackageSignature: String,
dependencies: Set<PatchClass> = setOf(),
) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) {
internal val gmsCoreVendorOption =
internal val gmsCoreVendorGroupIdOption =
stringPatchOption(
key = "gmsCoreVendor",
default = "com.mgoogle",
key = "gmsCoreVendorGroupId",
default = "app.revanced",
values =
mapOf(
"Vanced" to "com.mgoogle",
"ReVanced" to "app.revanced",
),
title = "GmsCore Vendor",
description = "The group id of the GmsCore vendor.",
title = "GmsCore vendor group ID",
description = "The vendor's group ID for GmsCore.",
required = true,
) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) }
) { it!!.matches(Regex(PACKAGE_NAME_REGEX_PATTERN)) }
protected val gmsCoreVendor by gmsCoreVendorOption
protected val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
@Deprecated("Use gmsCoreVendorGroupId instead.", ReplaceWith("gmsCoreVendorGroupId"))
protected val gmsCoreVendor by gmsCoreVendorGroupIdOption
override fun execute(context: ResourceContext) {
AddResourcesPatch(BaseGmsCoreSupportResourcePatch::class)
@@ -70,12 +72,12 @@ abstract class BaseGmsCoreSupportResourcePatch(
// Spoof package name and signature.
applicationNode.adoptChild("meta-data") {
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_NAME")
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME")
setAttribute("android:value", fromPackageName)
}
applicationNode.adoptChild("meta-data") {
setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_SIGNATURE")
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE")
setAttribute("android:value", spoofedPackageSignature)
}
@@ -83,7 +85,7 @@ abstract class BaseGmsCoreSupportResourcePatch(
applicationNode.adoptChild("meta-data") {
// TODO: The name of this metadata should be dynamic.
setAttribute("android:name", "app.revanced.MICROG_PACKAGE_NAME")
setAttribute("android:value", "$gmsCoreVendor.android.gms")
setAttribute("android:value", "$gmsCoreVendorGroupId.android.gms")
}
}
}
@@ -110,11 +112,16 @@ abstract class BaseGmsCoreSupportResourcePatch(
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
).replace(
"com.google.android.c2dm",
"$gmsCoreVendor.android.c2dm",
"$gmsCoreVendorGroupId.android.c2dm",
).replace(
"</queries>",
"<package android:name=\"$gmsCoreVendor.android.gms\"/></queries>",
"<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
),
)
}
private companion object {
private const val VANCED_VENDOR = "com.mgoogle"
private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$"
}
}

View File

@@ -49,7 +49,8 @@ abstract class BaseIntegrationsPatch(
opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {},
private val insertIndexResolver: ((Method) -> Int) = object : IHookInsertIndexResolver {},
private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
) : MethodFingerprint(
returnType,
accessFlags,
@@ -58,18 +59,45 @@ abstract class BaseIntegrationsPatch(
strings,
customFingerprint,
) {
@Deprecated("Previous constructor that is missing the insert index." +
"Here only for binary compatibility, " +
"and this can be removed after the next major version update.")
constructor(
returnType: String? = null,
accessFlags: Int? = null,
parameters: Iterable<String>? = null,
opcodes: Iterable<Opcode?>? = null,
strings: Iterable<String>? = null,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}
) : this(
returnType,
accessFlags,
parameters,
opcodes,
strings,
customFingerprint,
object : IHookInsertIndexResolver {},
contextRegisterResolver
)
fun invoke(integrationsDescriptor: String) {
result?.mutableMethod?.let { method ->
val insertIndex = insertIndexResolver(method)
val contextRegister = contextRegisterResolver(method)
method.addInstruction(
0,
"sput-object v$contextRegister, " +
"$integrationsDescriptor->context:Landroid/content/Context;",
insertIndex,
"invoke-static/range { v$contextRegister .. v$contextRegister }, " +
"$integrationsDescriptor->setContext(Landroid/content/Context;)V",
)
} ?: throw PatchException("Could not find hook target fingerprint.")
}
interface IHookInsertIndexResolver : (Method) -> Int {
override operator fun invoke(method: Method) = 0
}
interface IRegisterResolver : (Method) -> Int {
override operator fun invoke(method: Method) = method.implementation!!.registerCount - 1
}

View File

@@ -1,10 +1,14 @@
package app.revanced.patches.tiktok.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object InitFingerprint : IntegrationsFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AwemeHostApplication;") &&
methodDef.name == "onCreate"
methodDef.name == "<init>"
},
)
insertIndexResolver = { 1 } // Insert after call to super class.
)

View File

@@ -36,9 +36,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
],
),
],

View File

@@ -19,8 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -31,12 +30,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@@ -46,7 +49,7 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.ADS.addPreferences(
SwitchPreference("revanced_hide_get_premium"),
SwitchPreference("revanced_hide_get_premium")
)
GetPremiumViewFingerprint.result?.let {
@@ -70,7 +73,7 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {
:allow
nop
# Layout width/height is then passed to a protected class method.
""",
"""
)
}
} ?: throw GetPremiumViewFingerprint.exception

View File

@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -35,35 +35,38 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object VideoAdsPatch : BytecodePatch(
setOf(LoadVideoAdsFingerprint),
setOf(LoadVideoAdsFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.ADS.addPreferences(
SwitchPreference("revanced_hide_video_ads"),
SwitchPreference("revanced_hide_video_ads")
)
val loadVideoAdsFingerprintMethod = LoadVideoAdsFingerprint.result!!.mutableMethod
loadVideoAdsFingerprintMethod.addInstructionsWithLabels(
0,
"""
0, """
invoke-static { }, Lapp/revanced/integrations/youtube/patches/VideoAdsPatch;->shouldShowAds()Z
move-result v0
if-nez v0, :show_video_ads
return-void
""",
ExternalLabel("show_video_ads", loadVideoAdsFingerprintMethod.getInstruction(0)),
ExternalLabel("show_video_ads", loadVideoAdsFingerprintMethod.getInstruction(0))
)
}
}

View File

@@ -23,9 +23,13 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
],
),
],
@@ -39,7 +43,6 @@ object CopyVideoUrlBytecodePatch : BytecodePatch(emptySet()) {
)
override fun execute(context: BytecodeContext) {
// Initialize buttons and inject visibility control
BUTTONS_DESCRIPTORS.forEach { descriptor ->
PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")

View File

@@ -17,12 +17,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Remove viewer discretion dialog",
description = "Adds an option to remove the dialog that appears when opening a video that has been age-restricted " +
"by accepting it automatically. This does not bypass the age restriction.",
"by accepting it automatically. This does not bypass the age restriction.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -33,26 +32,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object RemoveViewerDiscretionDialogPatch : BytecodePatch(
setOf(CreateDialogFingerprint),
setOf(CreateDialogFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/RemoveViewerDiscretionDialogPatch;->" +
"confirmDialog(Landroid/app/AlertDialog;)V"
"confirmDialog(Landroid/app/AlertDialog;)V"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_remove_viewer_discretion_dialog"),
SwitchPreference("revanced_remove_viewer_discretion_dialog")
)
CreateDialogFingerprint.result?.mutableMethod?.apply {

View File

@@ -0,0 +1,79 @@
package app.revanced.patches.youtube.interaction.downloads
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.interaction.downloads.fingerprints.OfflineVideoEndpointFingerprint
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint
import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.util.resultOrThrow
@Patch(
name = "Downloads",
description = "Adds support to download videos with an external downloader app " +
"using the in-app download button or a video player action button.",
dependencies = [
DownloadsResourcePatch::class,
PlayerControlsBytecodePatch::class,
VideoInformationPatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
],
),
],
)
@Suppress("unused")
object DownloadsPatch : BytecodePatch(
setOf(
OfflineVideoEndpointFingerprint,
MainActivityFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DownloadsPatch;"
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
override fun execute(context: BytecodeContext) {
PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
// Main activity is used to launch downloader intent.
MainActivityFingerprint.resultOrThrow().mutableMethod.apply {
addInstruction(
implementation!!.instructions.lastIndex,
"invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
)
}
OfflineVideoEndpointFingerprint.resultOrThrow().mutableMethod.apply {
addInstructionsWithLabels(
0,
"""
invoke-static/range {p3 .. p3}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick(Ljava/lang/String;)Z
move-result v0
if-eqz v0, :show_native_downloader
return-void
:show_native_downloader
nop
"""
)
}
}
}

View File

@@ -21,7 +21,7 @@ import app.revanced.util.copyResources
AddResourcesPatch::class,
],
)
internal object ExternalDownloadsResourcePatch : ResourcePatch() {
internal object DownloadsResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
AddResourcesPatch(this::class)
@@ -31,6 +31,7 @@ internal object ExternalDownloadsResourcePatch : ResourcePatch() {
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_external_downloader"),
SwitchPreference("revanced_external_downloader_action_button"),
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT),
),
),

View File

@@ -1,54 +0,0 @@
package app.revanced.patches.youtube.interaction.downloads
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.video.information.VideoInformationPatch
@Patch(
name = "External downloads",
description = "Adds support to download and save YouTube videos using an external downloader app.",
dependencies = [
ExternalDownloadsResourcePatch::class,
PlayerControlsBytecodePatch::class,
VideoInformationPatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
)
@Suppress("unused")
object ExternalDownloadsBytecodePatch : BytecodePatch(emptySet()) {
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
override fun execute(context: BytecodeContext) {
/*
initialize the control
*/
PlayerControlsBytecodePatch.initializeControl(
"$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V",
)
/*
add code to change the visibility of the control
*/
PlayerControlsBytecodePatch.injectVisibilityCheckCall(
"$BUTTON_DESCRIPTOR->changeVisibility(Z)V",
)
}
}

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.interaction.downloads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object OfflineVideoEndpointFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf(
"Ljava/util/Map;",
"L",
"Ljava/lang/String", // VideoId
"L"),
strings = listOf("Object is not an offlineable video: ")
)

View File

@@ -32,26 +32,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object DisablePreciseSeekingGesturePatch : BytecodePatch(
setOf(IsSwipingUpFingerprint),
setOf(IsSwipingUpFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;->" +
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_disable_precise_seeking_gesture"),
SwitchPreference("revanced_disable_precise_seeking_gesture")
)
IsSwipingUpFingerprint.result?.let {
@@ -64,9 +68,9 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch(
replaceInstruction(
addMovementIndex,
"invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR",
"invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR"
)
}
} ?: throw IsSwipingUpFingerprint.exception
}
}
}

View File

@@ -22,8 +22,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
name = "Seekbar tapping",
description = "Adds an option to enable tap-to-seek on the seekbar of the video player.",
dependencies = [
IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class,
],
IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
@@ -35,25 +34,29 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object EnableSeekbarTappingPatch : BytecodePatch(
setOf(
OnTouchEventHandlerFingerprint,
SeekbarTappingFingerprint,
),
SeekbarTappingFingerprint
)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_seekbar_tapping"),
SwitchPreference("revanced_seekbar_tapping")
)
// Find the required methods to tap the seekbar.
@@ -95,9 +98,9 @@ object EnableSeekbarTappingPatch : BytecodePatch(
${oMethod.toInvokeInstructionString()}
${nMethod.toInvokeInstructionString()}
""",
ExternalLabel("disabled", getInstruction(insertIndex)),
ExternalLabel("disabled", getInstruction(insertIndex))
)
}
} ?: throw SeekbarTappingFingerprint.exception
}
}
}

View File

@@ -30,20 +30,24 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
],
use = false,
use = false
)
@Suppress("unused")
object EnableSlideToSeekPatch : BytecodePatch(
setOf(
SlideToSeekFingerprint,
DoubleSpeedSeekNoticeFingerprint,
),
DoubleSpeedSeekNoticeFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/SlideToSeekPatch;"
@@ -51,14 +55,14 @@ object EnableSlideToSeekPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_slide_to_seek"),
SwitchPreference("revanced_slide_to_seek")
)
arrayOf(
// Restore the behaviour to slide to seek.
SlideToSeekFingerprint,
// Disable the double speed seek notice.
DoubleSpeedSeekNoticeFingerprint,
DoubleSpeedSeekNoticeFingerprint
).map {
it.result ?: throw it.exception
}.forEach {
@@ -72,9 +76,9 @@ object EnableSlideToSeekPatch : BytecodePatch(
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSlideToSeekDisabled()Z
move-result v$isEnabledRegister
""",
"""
)
}
}
}
}
}

View File

@@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
dependencies = [
IntegrationsPatch::class,
PlayerTypeHookPatch::class,
SwipeControlsResourcePatch::class,
SwipeControlsResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -36,19 +36,23 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object SwipeControlsBytecodePatch : BytecodePatch(
setOf(
MainActivityFingerprint,
SwipeControlsHostActivityFingerprint,
),
SwipeControlsHostActivityFingerprint
)
) {
override fun execute(context: BytecodeContext) {
val wrapperClass = SwipeControlsHostActivityFingerprint.result!!.mutableClass
@@ -70,9 +74,9 @@ object SwipeControlsBytecodePatch : BytecodePatch(
accessFlags and AccessFlags.FINAL.value.inv(),
annotations,
hiddenApiRestrictions,
implementation,
implementation
).toMutable()
}
}
}
}
}

View File

@@ -15,6 +15,7 @@ import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
@Patch(
name = "Disable auto captions",
description = "Adds an option to disable captions from being automatically enabled.",
@@ -33,34 +34,38 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
],
)
@Suppress("unused")
object AutoCaptionsPatch : BytecodePatch(
setOf(StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint),
setOf(StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_auto_captions"),
SwitchPreference("revanced_auto_captions")
)
mapOf(
StartVideoInformerFingerprint to 0,
SubtitleButtonControllerFingerprint to 1,
SubtitleButtonControllerFingerprint to 1
).forEach { (fingerprint, enabled) ->
fingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x$enabled
sput-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
""",
"""
) ?: throw fingerprint.exception
}
@@ -76,7 +81,7 @@ object AutoCaptionsPatch : BytecodePatch(
return v0
:auto_captions_enabled
nop
""",
"""
)
}
}

View File

@@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
dependencies = [
ResourceMappingPatch::class,
LithoFilterPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -33,12 +33,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideButtonsPatch : ResourcePatch() {
@@ -60,9 +64,9 @@ object HideButtonsPatch : ResourcePatch() {
SwitchPreference("revanced_hide_thanks_button"),
SwitchPreference("revanced_hide_clip_button"),
SwitchPreference("revanced_hide_playlist_button"),
SwitchPreference("revanced_hide_shop_button"),
SwitchPreference("revanced_hide_shop_button")
),
),
)
)
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)

View File

@@ -27,7 +27,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
IntegrationsPatch::class,
SettingsPatch::class,
ResourceMappingPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -43,22 +43,26 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideAutoplayButtonPatch : BytecodePatch(
setOf(LayoutConstructorFingerprint),
setOf(LayoutConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_hide_autoplay_button"),
SwitchPreference("revanced_hide_autoplay_button")
)
LayoutConstructorFingerprint.result?.mutableMethod?.apply {
@@ -86,8 +90,8 @@ object HideAutoplayButtonPatch : BytecodePatch(
move-result v$clobberRegister
if-eqz v$clobberRegister, :hidden
""",
ExternalLabel("hidden", jumpInstruction),
ExternalLabel("hidden", jumpInstruction)
)
} ?: throw LayoutConstructorFingerprint.exception
}
}
}

View File

@@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.Opcode
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -34,22 +34,26 @@ import com.android.tools.smali.dexlib2.Opcode
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideCaptionsButtonPatch : BytecodePatch(
setOf(SubtitleButtonControllerFingerprint),
setOf(SubtitleButtonControllerFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_hide_captions_button"),
SwitchPreference("revanced_hide_captions_button")
)
val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
@@ -63,7 +67,7 @@ object HideCaptionsButtonPatch : BytecodePatch(
insertIndex,
"""
invoke-static {v0}, Lapp/revanced/integrations/youtube/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V
""",
"""
)
}
}

View File

@@ -10,10 +10,10 @@ import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.*
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.ANDROID_AUTOMOTIVE_STRING
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.AddCreateButtonViewFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@@ -24,8 +24,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
ResolvePivotBarFingerprintsPatch::class,
AddResourcesPatch::class,
NavigationBarHookPatch::class,
],
compatiblePackages = [
CompatiblePackage(
@@ -41,9 +41,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37",
],
),
],
@@ -72,53 +76,7 @@ object NavigationButtonsPatch : BytecodePatch(
),
)
/*
* Resolve fingerprints
*/
val initializeButtonsResult = InitializeButtonsFingerprint.result!!
val fingerprintResults =
arrayOf(PivotBarEnumFingerprint, PivotBarButtonsViewFingerprint)
.onEach {
if (!it.resolve(
context,
initializeButtonsResult.mutableMethod,
initializeButtonsResult.mutableClass,
)
) {
throw it.exception
}
}
.map { it.result!!.scanResult.patternScanResult!! }
val enumScanResult = fingerprintResults[0]
val buttonViewResult = fingerprintResults[1]
val enumHookInsertIndex = enumScanResult.startIndex + 2
val buttonHookInsertIndex = buttonViewResult.endIndex
/*
* Inject hooks
*/
val enumHook = "sput-object v$REGISTER_TEMPLATE_REPLACEMENT, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->lastNavigationButton:Ljava/lang/Enum;"
val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideButton(Landroid/view/View;)V"
// Inject bottom to top to not mess up the indices
mapOf(
buttonHook to buttonHookInsertIndex,
enumHook to enumHookInsertIndex,
).forEach { (hook, insertIndex) ->
initializeButtonsResult.mutableMethod.injectHook(hook, insertIndex)
}
/*
* Hide create or switch it with notifications buttons.
*/
// Switch create with notifications button.
AddCreateButtonViewFingerprint.result?.let {
it.mutableMethod.apply {
val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match ->
@@ -126,7 +84,8 @@ object NavigationButtonsPatch : BytecodePatch(
}!!.index
val conditionalCheckIndex = stringIndex - 1
val conditionRegister = getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA
val conditionRegister =
getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA
addInstructions(
conditionalCheckIndex,
@@ -138,26 +97,7 @@ object NavigationButtonsPatch : BytecodePatch(
}
} ?: throw AddCreateButtonViewFingerprint.exception
/*
* Resolve fingerprints
*/
InitializeButtonsFingerprint.result!!.let {
if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) {
throw PivotBarCreateButtonViewFingerprint.exception
}
}
PivotBarCreateButtonViewFingerprint.result!!.apply {
val insertIndex = scanResult.patternScanResult!!.endIndex
/*
* Inject hooks
*/
val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V"
mutableMethod.injectHook(hook, insertIndex)
}
// Hook navigation button created, in order to hide them.
NavigationBarHookPatch.hookNavigationButtonCreated(INTEGRATIONS_CLASS_DESCRIPTOR)
}
}

View File

@@ -1,38 +0,0 @@
package app.revanced.patches.youtube.layout.buttons.navigation
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.InitializeButtonsFingerprint
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.PivotBarConstructorFingerprint
import app.revanced.util.exception
@Patch(
description = "Resolves necessary fingerprints.",
dependencies = [ResourceMappingPatch::class],
)
internal object ResolvePivotBarFingerprintsPatch : BytecodePatch(
setOf(PivotBarConstructorFingerprint),
) {
internal var imageOnlyTabResourceId: Long = -1
override fun execute(context: BytecodeContext) {
// imageOnlyTabResourceId is used in InitializeButtonsFingerprint fingerprint
ResourceMappingPatch.resourceMappings.find { it.type == "layout" && it.name == "image_only_tab" }
?.let { imageOnlyTabResourceId = it.id } ?: throw PatchException("Failed to find resource")
PivotBarConstructorFingerprint.result?.let {
// Resolve InitializeButtonsFingerprint on the class of the method
// which PivotBarConstructorFingerprint resolved to
if (!InitializeButtonsFingerprint.resolve(
context,
it.classDef,
)
) {
throw InitializeButtonsFingerprint.exception
}
} ?: throw PivotBarConstructorFingerprint.exception
}
}

View File

@@ -1,12 +0,0 @@
package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object PivotBarButtonsViewFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL_RANGE,
Opcode.MOVE_RESULT_OBJECT, // target reference
Opcode.GOTO,
),
)

View File

@@ -1,13 +0,0 @@
package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_DIRECT_RANGE,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
),
)

View File

@@ -1,15 +0,0 @@
package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object PivotBarEnumFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_NEZ, // target reference
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
),
)

View File

@@ -1,30 +0,0 @@
package app.revanced.patches.youtube.layout.buttons.navigation.utils
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import com.android.tools.smali.dexlib2.Opcode.MOVE_RESULT_OBJECT
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
internal object InjectionUtils {
const val REGISTER_TEMPLATE_REPLACEMENT: String = "REGISTER_INDEX"
/**
* Injects an instruction into insertIndex of the hook.
* @param hook The hook to insert.
* @param insertIndex The index to insert the instruction at.
* [MOVE_RESULT_OBJECT] has to be the previous instruction before [insertIndex].
*/
fun MutableMethod.injectHook(hook: String, insertIndex: Int) {
val injectTarget = this
// Register to pass to the hook
val registerIndex = insertIndex - 1 // MOVE_RESULT_OBJECT is always the previous instruction
val register = injectTarget.getInstruction<OneRegisterInstruction>(registerIndex).registerA
injectTarget.addInstruction(
insertIndex,
hook.replace("REGISTER_INDEX", register.toString()),
)
}
}

View File

@@ -22,7 +22,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -38,22 +38,26 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HidePlayerButtonsPatch : BytecodePatch(
setOf(PlayerControlsVisibilityModelFingerprint),
setOf(PlayerControlsVisibilityModelFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_hide_player_buttons"),
SwitchPreference("revanced_hide_player_buttons")
)
PlayerControlsVisibilityModelFingerprint.result?.apply {
@@ -72,7 +76,7 @@ object HidePlayerButtonsPatch : BytecodePatch(
invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z
move-result v$hasPreviousParameterRegister
""",
"""
)
} ?: throw PlayerControlsVisibilityModelFingerprint.exception
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.albumcards
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.albumcards.fingerprints.AlbumCardsFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
description = "Adds an option to hide album cards below artist descriptions.",
dependencies = [
IntegrationsPatch::class,
AlbumCardsResourcePatch::class,
AlbumCardsResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object AlbumCardsPatch : BytecodePatch(
setOf(AlbumCardsFingerprint),
setOf(AlbumCardsFingerprint)
) {
override fun execute(context: BytecodeContext) {
AlbumCardsFingerprint.result?.let {
@@ -54,9 +58,9 @@ object AlbumCardsPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static {v$albumCardViewRegister}, " +
"Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" +
"->" +
"hideAlbumCard(Landroid/view/View;)V",
"Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" +
"->" +
"hideAlbumCard(Landroid/view/View;)V"
)
}
} ?: throw AlbumCardsFingerprint.exception

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.breakingnews
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.breakingnews.fingerprints.BreakingNewsFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
description = "Adds an option to hide the breaking news shelf on the homepage tab.",
dependencies = [
IntegrationsPatch::class,
BreakingNewsResourcePatch::class,
BreakingNewsResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object BreakingNewsPatch : BytecodePatch(
setOf(BreakingNewsFingerprint),
setOf(BreakingNewsFingerprint)
) {
override fun execute(context: BytecodeContext) {
BreakingNewsFingerprint.result?.let {
@@ -59,9 +63,11 @@ object BreakingNewsPatch : BytecodePatch(
Lapp/revanced/integrations/youtube/patches/HideBreakingNewsPatch;
->
hideBreakingNews(Landroid/view/View;)V
""",
"""
)
}
} ?: throw BreakingNewsFingerprint.exception
}
}

View File

@@ -16,7 +16,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
dependencies = [
SettingsPatch::class,
LithoFilterPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -32,12 +32,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object CommentsPatch : ResourcePatch() {
@@ -52,9 +56,9 @@ object CommentsPatch : ResourcePatch() {
"revanced_comments_screen",
preferences = setOf(
SwitchPreference("revanced_hide_comments_section"),
SwitchPreference("revanced_hide_preview_comment"),
),
),
SwitchPreference("revanced_hide_preview_comment")
)
)
)
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.crowdfundingbox
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
@@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
description = "Adds an option to hide the crowdfunding box between the player and video description.",
dependencies = [
IntegrationsPatch::class,
CrowdfundingBoxResourcePatch::class,
CrowdfundingBoxResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object CrowdfundingBoxPatch : BytecodePatch(
setOf(CrowdfundingBoxFingerprint),
setOf(CrowdfundingBoxFingerprint)
) {
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V"

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.endscreencards
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -11,7 +12,6 @@ import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.Layo
import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutIconFingerprint
import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutVideoFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
@Patch(
@@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
description = "Adds an option to hide suggested video cards at the end of videos.",
dependencies = [
IntegrationsPatch::class,
HideEndscreenCardsResourcePatch::class,
HideEndscreenCardsResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -35,12 +35,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideEndscreenCardsPatch : BytecodePatch(
@@ -48,7 +52,7 @@ object HideEndscreenCardsPatch : BytecodePatch(
LayoutCircleFingerprint,
LayoutIconFingerprint,
LayoutVideoFingerprint,
),
)
) {
override fun execute(context: BytecodeContext) {
fun MethodFingerprint.injectHideCall() {
@@ -59,7 +63,7 @@ object HideEndscreenCardsPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V",
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
)
}
}
@@ -67,7 +71,7 @@ object HideEndscreenCardsPatch : BytecodePatch(
listOf(
LayoutCircleFingerprint,
LayoutIconFingerprint,
LayoutVideoFingerprint,
LayoutVideoFingerprint
).forEach(MethodFingerprint::injectHideCall)
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.filterbar
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -10,7 +11,6 @@ import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.FilterBarHeightFingerprint
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.RelatedChipCloudFingerprint
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.SearchResultsChipBarFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -32,20 +32,24 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideFilterBarPatch : BytecodePatch(
setOf(
RelatedChipCloudFingerprint,
SearchResultsChipBarFingerprint,
FilterBarHeightFingerprint,
),
FilterBarHeightFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/HideFilterBarPatch;"
@@ -60,7 +64,7 @@ object HideFilterBarPatch : BytecodePatch(
RelatedChipCloudFingerprint.patch<OneRegisterInstruction>(1) { register ->
"invoke-static { v$register }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
}
SearchResultsChipBarFingerprint.patch<OneRegisterInstruction>(-1, -2) { register ->
@@ -82,7 +86,7 @@ object HideFilterBarPatch : BytecodePatch(
private fun <RegisterInstruction : OneRegisterInstruction> MethodFingerprint.patch(
insertIndexOffset: Int = 0,
hookRegisterOffset: Int = 0,
instructions: (Int) -> String,
instructions: (Int) -> String
) =
result?.let {
it.mutableMethod.apply {

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.floatingmicrophone
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -7,7 +8,6 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.floatingmicrophone.fingerprints.ShowFloatingMicrophoneButtonFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
@@ -28,16 +28,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideFloatingMicrophoneButtonPatch : BytecodePatch(
setOf(ShowFloatingMicrophoneButtonFingerprint),
setOf(ShowFloatingMicrophoneButtonFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/HideFloatingMicrophoneButtonPatch;"
@@ -54,7 +58,7 @@ object HideFloatingMicrophoneButtonPatch : BytecodePatch(
"""
invoke-static {v$showButtonRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z
move-result v$showButtonRegister
""",
"""
)
}
} ?: throw ShowFloatingMicrophoneButtonFingerprint.exception

View File

@@ -18,8 +18,7 @@ import app.revanced.util.exception
dependencies = [SettingsPatch::class, IntegrationsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.37.36",
"18.38.44",
"18.43.45",
@@ -29,16 +28,20 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object DisableFullscreenAmbientModePatch : BytecodePatch(
setOf(InitializeAmbientModeFingerprint),
setOf(InitializeAmbientModeFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/DisableFullscreenAmbientModePatch;"
@@ -47,7 +50,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_disable_fullscreen_ambient_mode"),
SwitchPreference("revanced_disable_fullscreen_ambient_mode")
)
InitializeAmbientModeFingerprint.result?.let {
@@ -57,7 +60,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch(
addInstruction(
moveIsEnabledIndex,
"invoke-static { }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->enableFullScreenAmbientMode()Z",
"$INTEGRATIONS_CLASS_DESCRIPTOR->enableFullScreenAmbientMode()Z"
)
}
} ?: throw InitializeAmbientModeFingerprint.exception

View File

@@ -12,6 +12,7 @@ import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
@@ -20,8 +21,10 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElemen
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -33,6 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
LithoFilterPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class // Used by Keyword Content filter.
],
compatiblePackages = [
CompatiblePackage(
@@ -48,9 +53,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37",
],
),
],
@@ -65,6 +74,8 @@ object HideLayoutComponentsPatch : BytecodePatch(
"Lapp/revanced/integrations/youtube/patches/components/DescriptionComponentsFilter;"
private const val CUSTOM_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/youtube/patches/components/CustomFilter;"
private const val KEYWORD_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/youtube/patches/components/KeywordContentFilter;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
@@ -90,6 +101,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_emergency_box"),
SwitchPreference("revanced_hide_expandable_chip"),
SwitchPreference("revanced_hide_info_panels"),
SwitchPreference("revanced_hide_join_membership_button"),
SwitchPreference("revanced_hide_medical_panels"),
SwitchPreference("revanced_hide_quick_actions"),
SwitchPreference("revanced_hide_related_videos"),
@@ -104,7 +116,6 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_feed_survey"),
SwitchPreference("revanced_hide_for_you_shelf"),
SwitchPreference("revanced_hide_image_shelf"),
SwitchPreference("revanced_hide_join_membership_button"),
SwitchPreference("revanced_hide_latest_posts_ads"),
SwitchPreference("revanced_hide_mix_playlists"),
SwitchPreference("revanced_hide_movies_section"),
@@ -113,6 +124,20 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_search_result_shelf_header"),
)
SettingsPatch.PreferenceScreen.FEED.addPreferences(
PreferenceScreen(
key = "revanced_hide_keyword_content_screen",
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_hide_keyword_content_home"),
SwitchPreference("revanced_hide_keyword_content_subscriptions"),
SwitchPreference("revanced_hide_keyword_content_search"),
TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE),
NonInteractivePreference("revanced_hide_keyword_content_about")
)
)
)
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_hide_gray_separator"),
PreferenceScreen(
@@ -132,19 +157,19 @@ object HideLayoutComponentsPatch : BytecodePatch(
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
LithoFilterPatch.addFilter(DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME)
LithoFilterPatch.addFilter(KEYWORD_FILTER_CLASS_NAME)
LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_NAME)
// region Mix playlists
ParseElementFromBufferFingerprint.result?.let { result ->
val returnEmptyComponentInstruction =
result.mutableMethod.getInstructions().last { it.opcode == Opcode.INVOKE_STATIC }
ParseElementFromBufferFingerprint.resultOrThrow().let { result ->
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex
result.mutableMethod.apply {
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex
val conversionContextRegister =
getInstruction<TwoRegisterInstruction>(consumeByteBufferIndex - 2).registerA
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
val returnEmptyComponentInstruction = getInstructions().last { it.opcode == Opcode.INVOKE_STATIC }
addInstructionsWithLabels(
consumeByteBufferIndex,
@@ -156,15 +181,15 @@ object HideLayoutComponentsPatch : BytecodePatch(
ExternalLabel("return_empty_component", returnEmptyComponentInstruction),
)
}
} ?: throw ParseElementFromBufferFingerprint.exception
}
// endregion
// region Watermark (legacy code for old versions of YouTube)
ShowWatermarkFingerprint.also {
it.resolve(context, PlayerOverlayFingerprint.result?.classDef ?: throw PlayerOverlayFingerprint.exception)
}.result?.mutableMethod?.apply {
it.resolve(context, PlayerOverlayFingerprint.resultOrThrow().classDef)
}.resultOrThrow().mutableMethod.apply {
val index = implementation!!.instructions.size - 5
removeInstruction(index)
@@ -175,7 +200,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
move-result p2
""",
)
} ?: throw ShowWatermarkFingerprint.exception
}
// endregion
}

View File

@@ -23,7 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
HideInfocardsResourcePatch::class,
HideInfocardsResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -39,19 +39,23 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideInfoCardsPatch : BytecodePatch(
setOf(
InfocardsIncognitoParentFingerprint,
InfocardsMethodCallFingerprint,
),
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/components/HideInfoCardsFilterPatch;"
@@ -62,14 +66,14 @@ object HideInfoCardsPatch : BytecodePatch(
}.result!!.mutableMethod.apply {
val invokeInstructionIndex = implementation!!.instructions.indexOfFirst {
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
((it as ReferenceInstruction).reference.toString() == "Landroid/view/View;->setVisibility(I)V")
((it as ReferenceInstruction).reference.toString() == "Landroid/view/View;->setVisibility(I)V")
}
addInstruction(
invokeInstructionIndex,
"invoke-static {v${getInstruction<FiveRegisterInstruction>(invokeInstructionIndex).registerC}}," +
" Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V",
)
addInstruction(
invokeInstructionIndex,
"invoke-static {v${getInstruction<FiveRegisterInstruction>(invokeInstructionIndex).registerC}}," +
" Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
)
}
with(InfocardsMethodCallFingerprint.result!!) {
@@ -86,13 +90,12 @@ object HideInfoCardsPatch : BytecodePatch(
if-nez v$toggleRegister, :hide_info_cards
""",
ExternalLabel(
"hide_info_cards",
hideInfoCardsCallMethod.getInstruction(invokeInterfaceIndex + 1),
),
"hide_info_cards", hideInfoCardsCallMethod.getInstruction(invokeInterfaceIndex + 1)
)
)
}
// Info cards can also appear as litho components.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
}
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.loadmorebutton
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -7,7 +8,6 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.loadmorebutton.fingerprints.HideLoadMoreButtonFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
@@ -28,16 +28,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideLoadMoreButtonPatch : BytecodePatch(
setOf(HideLoadMoreButtonFingerprint),
setOf(HideLoadMoreButtonFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch;"
@@ -53,7 +57,7 @@ object HideLoadMoreButtonPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V",
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V"
)
}
} ?: throw HideLoadMoreButtonFingerprint.exception

View File

@@ -18,12 +18,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
LithoFilterPatch::class,
PlayerTypeHookPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -34,12 +33,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HidePlayerFlyoutMenuPatch : ResourcePatch() {
@@ -66,7 +69,7 @@ object HidePlayerFlyoutMenuPatch : ResourcePatch() {
SwitchPreference("${KEY}_audio_track"),
SwitchPreference("${KEY}_watch_in_vr"),
),
),
)
)
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)

View File

@@ -22,8 +22,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.43.45",
"18.44.41",
"18.45.43",
@@ -31,18 +30,22 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object DisableRollingNumberAnimationPatch : BytecodePatch(
setOf(
RollingNumberTextViewAnimationUpdateFingerprint,
),
RollingNumberTextViewAnimationUpdateFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/DisableRollingNumberAnimationsPatch;"
@@ -51,7 +54,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_disable_rolling_number_animations"),
SwitchPreference("revanced_disable_rolling_number_animations")
)
// Animations are disabled by preventing an Image from being applied to the text span,
@@ -75,7 +78,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch(
move-result v$freeRegister
if-nez v$freeRegister, :disable_animations
""",
ExternalLabel("disable_animations", getInstruction(blockEndIndex)),
ExternalLabel("disable_animations", getInstruction(blockEndIndex))
)
}
} ?: throw RollingNumberTextViewAnimationUpdateFingerprint.exception

View File

@@ -20,12 +20,11 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
IntegrationsPatch::class,
SettingsPatch::class,
SeekbarColorBytecodePatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -36,23 +35,27 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideSeekbarPatch : BytecodePatch(
setOf(SeekbarFingerprint),
setOf(SeekbarFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_hide_seekbar"),
SwitchPreference("revanced_hide_seekbar_thumbnail"),
SwitchPreference("revanced_hide_seekbar_thumbnail")
)
SeekbarFingerprint.result!!.let {
@@ -67,7 +70,7 @@ object HideSeekbarPatch : BytecodePatch(
return-void
:hide_seekbar
nop
""",
"""
)
}
}

View File

@@ -1,5 +1,8 @@
package app.revanced.patches.youtube.layout.hide.shorts
import app.revanced.util.exception
import app.revanced.util.findIndexForIdResource
import app.revanced.util.injectHideViewCall
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -8,18 +11,11 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.BottomNavigationBarFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.CreateShortsButtonsFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.ReelConstructorFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.RenderBottomNavigationBarFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.RenderBottomNavigationBarParentFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.SetPivotBarVisibilityFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.SetPivotBarVisibilityParentFingerprint
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.*
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.util.exception
import app.revanced.util.findIndexForIdResource
import app.revanced.util.injectHideViewCall
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -31,12 +27,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
IntegrationsPatch::class,
LithoFilterPatch::class,
HideShortsComponentsResourcePatch::class,
ResourceMappingPatch::class
ResourceMappingPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -47,9 +44,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37"
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
@@ -94,6 +95,7 @@ object HideShortsComponentsPatch : BytecodePatch(
ShortsButtons.entries.forEach { button -> button.injectHideCall(it.mutableMethod) }
} ?: throw CreateShortsButtonsFingerprint.exception
// endregion
// region Hide the Shorts buttons in newer versions of YouTube.
@@ -106,9 +108,8 @@ object HideShortsComponentsPatch : BytecodePatch(
// Hook to get the pivotBar view.
SetPivotBarVisibilityParentFingerprint.result?.let {
if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef)) {
if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef))
throw SetPivotBarVisibilityFingerprint.exception
}
SetPivotBarVisibilityFingerprint.result!!.let { result ->
result.mutableMethod.apply {
@@ -117,7 +118,7 @@ object HideShortsComponentsPatch : BytecodePatch(
addInstruction(
insertIndex,
"sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" +
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
)
}
}
@@ -125,9 +126,8 @@ object HideShortsComponentsPatch : BytecodePatch(
// Hook to hide the navigation bar when Shorts are being played.
RenderBottomNavigationBarParentFingerprint.result?.let {
if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef)) {
if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef))
throw RenderBottomNavigationBarFingerprint.exception
}
RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply {
addInstruction(0, "invoke-static { }, $FILTER_CLASS_DESCRIPTOR->hideNavigationBar()V")
@@ -144,7 +144,7 @@ object HideShortsComponentsPatch : BytecodePatch(
addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, $FILTER_CLASS_DESCRIPTOR->" +
"hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
"hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
)
}
} ?: throw BottomNavigationBarFingerprint.exception
@@ -152,11 +152,11 @@ object HideShortsComponentsPatch : BytecodePatch(
// endregion
}
private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
REMIX("reel_dyn_remix", "hideShortsRemixButton"),
SHARE("reel_dyn_share", "hideShortsShareButton")
;
SHARE("reel_dyn_share", "hideShortsShareButton");
fun injectHideCall(method: MutableMethod) {
val referencedIndex = method.findIndexForIdResource(resourceName)

View File

@@ -17,17 +17,32 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SHORTS.addPreferences(
SwitchPreference("revanced_hide_shorts"),
SwitchPreference("revanced_hide_shorts_home"),
SwitchPreference("revanced_hide_shorts_subscriptions"),
SwitchPreference("revanced_hide_shorts_search"),
// Shorts player components.
// Ideally each group should be ordered similar to how they appear in the UI
// since this Setting menu currently uses the ordering used here.
// Vertical row of buttons on right side of the screen.
SwitchPreference("revanced_hide_shorts_like_button"),
SwitchPreference("revanced_hide_shorts_dislike_button"),
SwitchPreference("revanced_hide_shorts_comments_button"),
SwitchPreference("revanced_hide_shorts_share_button"),
SwitchPreference("revanced_hide_shorts_remix_button"),
SwitchPreference("revanced_hide_shorts_sound_button"),
// Everything else.
SwitchPreference("revanced_hide_shorts_thanks_button"),
SwitchPreference("revanced_hide_shorts_join_button"),
SwitchPreference("revanced_hide_shorts_subscribe_button"),
SwitchPreference("revanced_hide_shorts_subscribe_button_paused"),
SwitchPreference("revanced_hide_shorts_thanks_button"),
SwitchPreference("revanced_hide_shorts_comments_button"),
SwitchPreference("revanced_hide_shorts_remix_button"),
SwitchPreference("revanced_hide_shorts_share_button"),
SwitchPreference("revanced_hide_shorts_info_panel"),
SwitchPreference("revanced_hide_shorts_channel_bar"),
SwitchPreference("revanced_hide_shorts_sound_button"),
SwitchPreference("revanced_hide_shorts_info_panel"),
SwitchPreference("revanced_hide_shorts_full_video_link_label"),
SwitchPreference("revanced_hide_shorts_video_title"),
SwitchPreference("revanced_hide_shorts_sound_metadata_label"),
SwitchPreference("revanced_hide_shorts_navigation_bar"),
)

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.suggestedvideoendscreen
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.hide.suggestedvideoendscreen.fingerprints.CreateEndScreenViewFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
@@ -17,8 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
dependencies = [IntegrationsPatch::class, DisableSuggestedVideoEndScreenResourcePatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.37.36",
"18.38.44",
"18.43.45",
@@ -28,16 +27,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object DisableSuggestedVideoEndScreenPatch : BytecodePatch(
setOf(CreateEndScreenViewFingerprint),
setOf(CreateEndScreenViewFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch;"
@@ -51,7 +54,7 @@ object DisableSuggestedVideoEndScreenPatch : BytecodePatch(
addInstruction(
addOnClickEventListenerIndex + 1,
"invoke-static {v$viewRegister}, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->closeEndScreen(Landroid/widget/ImageView;)V",
"$INTEGRATIONS_CLASS_DESCRIPTOR->closeEndScreen(Landroid/widget/ImageView;)V"
)
}
} ?: throw CreateEndScreenViewFingerprint.exception

View File

@@ -18,8 +18,7 @@ import app.revanced.util.exception
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.37.36",
"18.38.44",
"18.43.45",
@@ -29,35 +28,39 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object HideTimestampPatch : BytecodePatch(
setOf(TimeCounterFingerprint),
setOf(TimeCounterFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_hide_timestamp"),
SwitchPreference("revanced_hide_timestamp")
)
TimeCounterFingerprint.result?.apply {
mutableMethod.addInstructionsWithLabels(
0,
"""
0,
"""
invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideTimestampPatch;->hideTimestamp()Z
move-result v0
if-eqz v0, :hide_time
return-void
:hide_time
nop
""",
"""
)
} ?: throw TimeCounterFingerprint.exception
}

View File

@@ -18,8 +18,7 @@ import app.revanced.util.exception
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -30,22 +29,26 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object PlayerPopupPanelsPatch : BytecodePatch(
setOf(EngagementPanelControllerFingerprint),
setOf(EngagementPanelControllerFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_hide_player_popup_panels"),
SwitchPreference("revanced_hide_player_popup_panels")
)
val engagementPanelControllerMethod = EngagementPanelControllerFingerprint
@@ -62,7 +65,7 @@ object PlayerPopupPanelsPatch : BytecodePatch(
return-object v0
:player_popup_panels
nop
""",
"""
)
}
}

View File

@@ -24,9 +24,13 @@ import org.w3c.dom.Element
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
],
),
],

View File

@@ -32,6 +32,7 @@ import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@@ -53,17 +54,20 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object ReturnYouTubeDislikePatch : BytecodePatch(
@@ -80,8 +84,8 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
RollingNumberMeasureStaticLabelParentFingerprint,
RollingNumberMeasureAnimatedTextFingerprint,
RollingNumberTextViewFingerprint,
RollingNumberTextViewAnimationUpdateFingerprint,
),
RollingNumberTextViewAnimationUpdateFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch;"
@@ -89,8 +93,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
private fun MethodFingerprint.resultOrThrow() = result ?: throw exception
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
@@ -106,7 +108,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
listOf(
LikeFingerprint.toPatch(Vote.LIKE),
DislikeFingerprint.toPatch(Vote.DISLIKE),
RemoveLikeFingerprint.toPatch(Vote.REMOVE_LIKE),
RemoveLikeFingerprint.toPatch(Vote.REMOVE_LIKE)
).forEach { (fingerprint, vote) ->
fingerprint.result?.mutableMethod?.apply {
addInstructions(
@@ -114,7 +116,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
"""
const/4 v0, ${vote.value}
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->sendVote(I)V
""",
"""
)
} ?: throw fingerprint.exception
}
@@ -140,7 +142,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
val textDataClassType = TextComponentDataFingerprint.resultOrThrow().classDef.type
val insertIndex = indexOfFirstInstruction {
opcode == Opcode.NEW_INSTANCE &&
getReference<TypeReference>()?.type == textDataClassType
getReference<TypeReference>()?.type == textDataClassType
}
if (insertIndex < 0) throw PatchException("Could not find data creation instruction")
val tempRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
@@ -153,7 +155,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
.subList(insertIndex, insertIndex + 20)
.find {
it.opcode == Opcode.IPUT_OBJECT &&
it.getReference<FieldReference>()?.type == "Ljava/lang/CharSequence;"
it.getReference<FieldReference>()?.type == "Ljava/lang/CharSequence;"
} ?: throw PatchException("Could not find put object instruction")
val charSequenceRegister = (putFieldInstruction as TwoRegisterInstruction).registerA
@@ -165,7 +167,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
iget-object v$tempRegister, v$tempRegister, $conversionContextField
invoke-static {v$tempRegister, v$charSequenceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$charSequenceRegister
""",
"""
)
}
} ?: throw TextComponentConstructorFingerprint.exception
@@ -205,7 +207,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
:is_like
:ryd_disabled
nop
""",
"""
)
}
} ?: throw ShortsTextViewFingerprint.exception
@@ -233,13 +235,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
addInstruction(
startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V",
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
} ?: throw DislikesOldLayoutTextViewFingerprint.exception
// endregion
// region Hook rolling numbers.
// Do this last to allow patching old unsupported versions (if the user really wants),
@@ -270,7 +273,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
move-result-object v$freeRegister
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
""",
"""
)
}
} ?: throw RollingNumberSetterFingerprint.exception
@@ -290,7 +293,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
"""
invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
move-result v$measuredTextWidthRegister
""",
"""
)
}
} ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception
@@ -308,7 +311,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
"""
move-result v$freeRegister
invoke-static {p1, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
""",
"""
)
}
} ?: throw RollingNumberMeasureStaticLabelFingerprint.exception
@@ -327,7 +330,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
arrayOf(
initiallyCreatedTextViewMethod,
realTimeUpdateTextViewMethod,
realTimeUpdateTextViewMethod
).forEach { insertMethod ->
insertMethod.apply {
val setTextIndex = indexOfFirstInstruction {
@@ -344,13 +347,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
"""
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$textSpanRegister
""",
"""
)
}
}
} ?: throw RollingNumberTextViewFingerprint.exception
// endregion
}
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
@@ -358,6 +362,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
private enum class Vote(val value: Int) {
LIKE(1),
DISLIKE(-1),
REMOVE_LIKE(0),
REMOVE_LIKE(0)
}
}

View File

@@ -23,8 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -34,19 +33,23 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object WideSearchbarPatch : BytecodePatch(
setOf(
SetWordmarkHeaderFingerprint,
CreateSearchSuggestionsFingerprint,
),
CreateSearchSuggestionsFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@@ -56,7 +59,7 @@ object WideSearchbarPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.FEED.addPreferences(
SwitchPreference("revanced_wide_searchbar"),
SwitchPreference("revanced_wide_searchbar")
)
val result = CreateSearchSuggestionsFingerprint.result ?: throw CreateSearchSuggestionsFingerprint.exception
@@ -64,7 +67,7 @@ object WideSearchbarPatch : BytecodePatch(
// patch methods
mapOf(
SetWordmarkHeaderFingerprint to 1,
CreateSearchSuggestionsFingerprint to result.scanResult.patternScanResult!!.startIndex,
CreateSearchSuggestionsFingerprint to result.scanResult.patternScanResult!!.startIndex
).forEach { (fingerprint, callIndex) ->
context.walkMutable(callIndex, fingerprint).injectSearchBarHook()
}
@@ -82,6 +85,7 @@ object WideSearchbarPatch : BytecodePatch(
toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod
} ?: throw fromFingerprint.exception
/**
* Injects instructions required for certain methods.
*/
@@ -94,7 +98,7 @@ object WideSearchbarPatch : BytecodePatch(
"""
invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->enableWideSearchbar(Z)Z
move-result v$insertRegister
""",
"""
)
}
}

View File

@@ -19,8 +19,7 @@ import app.revanced.util.exception
dependencies = [IntegrationsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.37.36",
"18.38.44",
"18.43.45",
@@ -30,16 +29,20 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object RestoreOldSeekbarThumbnailsPatch : BytecodePatch(
setOf(FullscreenSeekbarThumbnailsFingerprint),
setOf(FullscreenSeekbarThumbnailsFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/RestoreOldSeekbarThumbnailsPatch;"
@@ -48,7 +51,7 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_restore_old_seekbar_thumbnails"),
SwitchPreference("revanced_restore_old_seekbar_thumbnails")
)
FullscreenSeekbarThumbnailsFingerprint.result?.mutableMethod?.apply {
@@ -56,7 +59,7 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch(
addInstruction(
moveResultIndex,
"invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z",
"invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z"
)
} ?: throw FullscreenSeekbarThumbnailsFingerprint.exception
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.sponsorblock
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -24,7 +25,6 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint
import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.*
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@@ -37,17 +37,20 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
description = "Adds options to enable and configure SponsorBlock, which can skip undesired video segments such as sponsored content.",
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
],
dependencies = [
IntegrationsPatch::class,
@@ -57,8 +60,8 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
// Used to prevent SponsorBlock from running on Shorts because SponsorBlock does not yet support Shorts.
PlayerTypeHookPatch::class,
PlayerControlsBytecodePatch::class,
SponsorBlockResourcePatch::class,
],
SponsorBlockResourcePatch::class
]
)
@Suppress("unused")
object SponsorBlockBytecodePatch : BytecodePatch(
@@ -66,8 +69,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
SeekbarFingerprint,
AppendTimeFingerprint,
LayoutConstructorFingerprint,
AutoRepeatParentFingerprint,
),
AutoRepeatParentFingerprint
)
) {
private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/sponsorblock/SegmentPlaybackController;"
@@ -80,9 +83,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
LayoutConstructorFingerprint.result?.let {
if (!ControlsOverlayFingerprint.resolve(context, it.classDef)) {
if (!ControlsOverlayFingerprint.resolve(context, it.classDef))
throw ControlsOverlayFingerprint.exception
}
} ?: throw LayoutConstructorFingerprint.exception
/*
@@ -91,7 +93,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
with(VideoInformationPatch) {
videoTimeHook(
INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR,
"setVideoTime",
"setVideoTime"
)
}
@@ -119,7 +121,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
seekbarMethod.addInstruction(
moveRectangleToRegisterIndex + 1,
"invoke-static/range {p0 .. p0}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V",
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
)
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
@@ -134,7 +136,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
seekbarMethod.addInstruction(
insertIndex,
"invoke-static {v${invokeInstruction.registerC}}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V",
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
)
break
}
@@ -152,7 +154,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
}
seekbarMethod.addInstruction(
i,
"invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V",
"invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V"
)
break
@@ -186,7 +188,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
"""
invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
""",
"""
)
}
@@ -199,7 +201,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
"""
invoke-static {p1}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V
invoke-static {p1}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V
""".trimIndent(),
""".trimIndent()
)
}
}
@@ -221,7 +223,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
"""
invoke-static {v$targetRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
""",
"""
)
// initialize the player controller
@@ -234,10 +236,10 @@ object SponsorBlockBytecodePatch : BytecodePatch(
val frameLayoutRegister = (getInstruction(startIndex + 2) as OneRegisterInstruction).registerA
addInstruction(
startIndex + 3,
"invoke-static {v$frameLayoutRegister}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V",
"invoke-static {v$frameLayoutRegister}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V"
)
}
} ?: throw ControlsOverlayFingerprint.exception
} ?: throw ControlsOverlayFingerprint.exception
// get rectangle field name
RectangleFieldInvalidatorFingerprint.resolve(context, seekbarSignatureResult.classDef)
@@ -256,8 +258,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
fun MutableMethod.replaceStringInstruction(index: Int, instruction: Instruction, with: String) {
val register = (instruction as OneRegisterInstruction).registerA
this.replaceInstruction(
index,
"const-string v$register, \"$with\"",
index, "const-string v$register, \"$with\""
)
}
for ((index, it) in method.implementation!!.instructions.withIndex()) {
@@ -267,12 +268,13 @@ object SponsorBlockBytecodePatch : BytecodePatch(
"replaceMeWithsetSponsorBarRect" -> method.replaceStringInstruction(
index,
it,
rectangleFieldName,
rectangleFieldName
)
}
}
} ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings")
// The vote and create segment buttons automatically change their visibility when appropriate,
// but if buttons are showing when the end of the video is reached then they will not automatically hide.
// Add a hook to forcefully hide when the end of the video is reached.
@@ -281,7 +283,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
it.resolve(context, AutoRepeatParentFingerprint.result!!.classDef)
}.result?.mutableMethod?.addInstruction(
0,
"invoke-static {}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V",
"invoke-static {}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V"
) ?: throw AutoRepeatFingerprint.exception
// TODO: isSBChannelWhitelisting implementation

View File

@@ -17,12 +17,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Spoof app version",
description = "Adds an option to trick YouTube into thinking you are running an older version of the app. " +
"This can be used to restore old UI elements and features.",
"This can be used to restore old UI elements and features.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -33,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object SpoofAppVersionPatch : BytecodePatch(
setOf(SpoofAppVersionFingerprint),
setOf(SpoofAppVersionFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch;"
@@ -55,7 +58,7 @@ object SpoofAppVersionPatch : BytecodePatch(
ListPreference(
key = "revanced_spoof_app_version_target",
summaryKey = null,
),
)
)
SpoofAppVersionFingerprint.result?.apply {
@@ -68,7 +71,7 @@ object SpoofAppVersionPatch : BytecodePatch(
"""
invoke-static {v$buildOverrideNameRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$buildOverrideNameRegister
""",
"""
)
} ?: throw SpoofAppVersionFingerprint.exception
}

View File

@@ -27,8 +27,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
@@ -39,16 +38,20 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object DisableResumingShortsOnStartupPatch : BytecodePatch(
setOf(UserWasInShortsFingerprint),
setOf(UserWasInShortsFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@@ -58,14 +61,14 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.SHORTS.addPreferences(
SwitchPreference("revanced_disable_resuming_shorts_player"),
SwitchPreference("revanced_disable_resuming_shorts_player")
)
UserWasInShortsFingerprint.result?.mutableMethod?.apply {
val listenableInstructionIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_INTERFACE &&
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
getReference<MethodReference>()?.name == "isDone"
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
getReference<MethodReference>()?.name == "isDone"
}
if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index")
val originalInstructionRegister = getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
@@ -74,7 +77,7 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch(
// Replace original instruction to preserve control flow label.
replaceInstruction(
listenableInstructionIndex,
"invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z",
"invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z"
)
addInstructionsWithLabels(
listenableInstructionIndex + 1,
@@ -84,7 +87,7 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch(
return-void
:show_startup_shorts_player
invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z
""",
"""
)
} ?: throw UserWasInShortsFingerprint.exception
}

View File

@@ -26,8 +26,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
arrayOf(
"com.google.android.youtube", arrayOf(
"18.32.39",
"18.37.36",
"18.38.44",
@@ -38,26 +37,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
),
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
)
)
]
)
@Suppress("unused")
object TabletMiniPlayerPatch : BytecodePatch(
setOf(
MiniPlayerDimensionsCalculatorParentFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint,
MiniPlayerOverrideFingerprint,
),
MiniPlayerOverrideFingerprint
)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_tablet_miniplayer"),
SwitchPreference("revanced_tablet_miniplayer")
)
// First resolve the fingerprints via the parent fingerprint.
@@ -74,8 +77,7 @@ object TabletMiniPlayerPatch : BytecodePatch(
// Insert right before the return instruction.
val secondInsertIndex = method.implementation!!.instructions.size - 1
method.insertOverride(
secondInsertIndex,
parameterRegister,
secondInsertIndex, parameterRegister
/** same register used to return **/
)
@@ -127,7 +129,7 @@ object TabletMiniPlayerPatch : BytecodePatch(
"""
invoke-static {v$overrideRegister}, Lapp/revanced/integrations/youtube/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z
move-result v$overrideRegister
""",
"""
)
}

View File

@@ -26,7 +26,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
ThemeResourcePatch::class,
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -41,16 +41,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object ThemeBytecodePatch : BytecodePatch(
setOf(UseGradientLoadingScreenFingerprint),
setOf(UseGradientLoadingScreenFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/theme/ThemePatch;"
@@ -73,7 +77,7 @@ object ThemeBytecodePatch : BytecodePatch(
"Dark green" to "#FF002905",
"Dark yellow" to "#FF282900",
"Dark orange" to "#FF291800",
"Dark red" to "#FF290000",
"Dark red" to "#FF290000"
),
title = "Dark theme background color",
description = "Can be a hex color (#AARRGGBB) or a color resource reference.",
@@ -91,7 +95,7 @@ object ThemeBytecodePatch : BytecodePatch(
"Light green" to "#FFCCFFCC",
"Light yellow" to "#FFFDFFCC",
"Light orange" to "#FFFFE6CC",
"Light red" to "#FFFFD6D6",
"Light red" to "#FFFFD6D6"
),
title = "Light theme background color",
description = "Can be a hex color (#AARRGGBB) or a color resource reference.",
@@ -101,7 +105,7 @@ object ThemeBytecodePatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_gradient_loading_screen"),
SwitchPreference("revanced_gradient_loading_screen")
)
UseGradientLoadingScreenFingerprint.result?.mutableMethod?.apply {
@@ -113,7 +117,7 @@ object ThemeBytecodePatch : BytecodePatch(
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled()Z
move-result v$isEnabledRegister
""",
"""
)
} ?: throw UseGradientLoadingScreenFingerprint.exception

View File

@@ -22,8 +22,10 @@ import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.reques
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@@ -38,6 +40,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class
],
compatiblePackages = [
CompatiblePackage(
@@ -53,9 +57,13 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
],
),
],
@@ -123,32 +131,49 @@ object AlternativeThumbnailsPatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
val entries = "revanced_alt_thumbnail_options_entries"
val values = "revanced_alt_thumbnail_options_entry_values"
SettingsPatch.PreferenceScreen.ALTERNATIVE_THUMBNAILS.addPreferences(
NonInteractivePreference(
"revanced_alt_thumbnail_about",
null, // Summary is dynamically updated based on the current settings.
tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsStatusPreference",
ListPreference("revanced_alt_thumbnail_home",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_subscription",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_library",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_player",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_search",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
SwitchPreference("revanced_alt_thumbnail_dearrow"),
SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"),
TextPreference("revanced_alt_thumbnail_dearrow_api_url"),
NonInteractivePreference(
"revanced_alt_thumbnail_dearrow_about",
// Custom about preference with link to the DeArrow website.
tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsAboutDeArrowPreference",
selectable = true,
),
SwitchPreference("revanced_alt_thumbnail_stills"),
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null),
SwitchPreference("revanced_alt_thumbnail_stills_fast"),
SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"),
TextPreference("revanced_alt_thumbnail_dearrow_api_url"),
NonInteractivePreference("revanced_alt_thumbnail_stills_about"),
SwitchPreference("revanced_alt_thumbnail_stills_fast"),
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
)
fun MethodFingerprint.getResultOrThrow() =
result ?: throw exception
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
also { resolve(context, fingerprint.getResultOrThrow().classDef) }.getResultOrThrow()
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
fun MethodFingerprint.resolveAndLetMutableMethod(
fingerprint: MethodFingerprint,
@@ -172,7 +197,7 @@ object AlternativeThumbnailsPatch : BytecodePatch(
// The URL is required for the failure callback hook, but the URL field is obfuscated.
// Add a helper get method that returns the URL field.
RequestFingerprint.getResultOrThrow().apply {
RequestFingerprint.resultOrThrow().apply {
// The url is the only string field that is set inside the constructor.
val urlFieldInstruction = mutableMethod.getInstructions().first {
if (it.opcode != Opcode.IPUT_OBJECT) return@first false

View File

@@ -14,10 +14,11 @@ import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParen
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(
name = "Always repeat",
description = "Adds an option to always repeat videos when they end.",
dependencies = [IntegrationsPatch::class, AddResourcesPatch::class],
dependencies = [IntegrationsPatch::class,AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
@@ -32,40 +33,44 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object AutoRepeatPatch : BytecodePatch(
setOf(AutoRepeatParentFingerprint),
setOf(AutoRepeatParentFingerprint)
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference("revanced_auto_repeat"),
SwitchPreference("revanced_auto_repeat")
)
// Get Result from the ParentFingerprint which is the playMethod we need to get.
//Get Result from the ParentFingerprint which is the playMethod we need to get.
val parentResult = AutoRepeatParentFingerprint.result
?: throw PatchException("ParentFingerprint did not resolve.")
// this one needs to be called when app/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true
//this one needs to be called when app/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true
val playMethod = parentResult.mutableMethod
AutoRepeatFingerprint.resolve(context, parentResult.classDef)
// String is: Laamp;->E()V
//String is: Laamp;->E()V
val methodToCall = playMethod.definingClass + "->" + playMethod.name + "()V"
// This is the method we search for
//This is the method we search for
val result = AutoRepeatFingerprint.result
?: throw PatchException("FingerPrint did not resolve.")
val method = result.mutableMethod
// Instructions to add to the smali code
//Instructions to add to the smali code
val instructions = """
invoke-static {}, Lapp/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat()Z
move-result v0
@@ -75,19 +80,20 @@ object AutoRepeatPatch : BytecodePatch(
return-void
"""
// Get the implementation so we can do a check for null and get instructions size.
//Get the implementation so we can do a check for null and get instructions size.
val implementation = method.implementation
?: throw PatchException("No Method Implementation found!")
// Since addInstructions needs an index which starts counting at 0 and size starts counting at 1,
// we have to remove 1 to get the latest instruction
//Since addInstructions needs an index which starts counting at 0 and size starts counting at 1,
//we have to remove 1 to get the latest instruction
val index = implementation.instructions.size - 1
// remove last instruction which is return-void
//remove last instruction which is return-void
method.removeInstruction(index)
// Add our own instructions there
method.addInstructionsWithLabels(index, instructions)
// Everything worked as expected, return Success
//Everything worked as expected, return Success
}
}

View File

@@ -28,16 +28,20 @@ import app.revanced.util.exception
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
],
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.37"
]
)
]
)
@Suppress("unused")
object SpoofDeviceDimensionsPatch : BytecodePatch(
setOf(DeviceDimensionsModelToStringFingerprint),
setOf(DeviceDimensionsModelToStringFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofDeviceDimensionsPatch;"
@@ -46,7 +50,7 @@ object SpoofDeviceDimensionsPatch : BytecodePatch(
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference("revanced_spoof_device_dimensions"),
SwitchPreference("revanced_spoof_device_dimensions")
)
DeviceDimensionsModelToStringFingerprint.result
@@ -58,13 +62,13 @@ object SpoofDeviceDimensionsPatch : BytecodePatch(
1 to "MinHeightOrWidth", // p1 = min height
2 to "MaxHeightOrWidth", // p2 = max height
3 to "MinHeightOrWidth", // p3 = min width
4 to "MaxHeightOrWidth", // p4 = max width
4 to "MaxHeightOrWidth" // p4 = max width
).map { (parameter, method) ->
"""
invoke-static { p$parameter }, $INTEGRATIONS_CLASS_DESCRIPTOR->get$method(I)I
move-result p$parameter
"""
}.joinToString("\n") { it },
}.joinToString("\n") { it }
) ?: throw DeviceDimensionsModelToStringFingerprint.exception
}
}
}

View File

@@ -1,47 +1,86 @@
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.Instruction35cInfo
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Client spoof",
description = "Adds options to spoof the client to allow video playback.",
dependencies = [SpoofSignaturePatch::class],
description = "Spoofs the client to allow video playback.",
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.35",
"19.03.36",
"19.04.37",
],
),
CompatiblePackage("com.google.android.youtube"),
],
)
object ClientSpoofPatch : BytecodePatch(
setOf(UserAgentHeaderBuilderFingerprint),
) {
object ClientSpoofPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE =
"Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;"
override fun execute(context: BytecodeContext) {
UserAgentHeaderBuilderFingerprint.result?.let { result ->
val insertIndex = result.scanResult.patternScanResult!!.endIndex
result.mutableMethod.apply {
val packageNameRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
override fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int,
) = filterMapInstruction35c<MethodCall>(
"Lapp/revanced/integrations",
classDef,
instruction,
instructionIndex,
)
addInstruction(insertIndex, "const-string v$packageNameRegister, \"$ORIGINAL_PACKAGE_NAME\"")
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
val (_, _, instructionIndex) = entry
// Replace the result of context.getPackageName(), if it is used in a user agent string.
mutableMethod.apply {
// After context.getPackageName() the result is moved to a register.
val targetRegister = (
getInstruction(instructionIndex + 1)
as? OneRegisterInstruction ?: return
).registerA
// IndexOutOfBoundsException is not possible here,
// but no such occurrences are present in the app.
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()
// This can technically also match non-user agent string builder append methods,
// but no such occurrences are present in the app.
if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) {
return
}
} ?: throw UserAgentHeaderBuilderFingerprint.exception
// Overwrite the result of context.getPackageName() with the original package name.
replaceInstruction(
instructionIndex + 1,
"const-string v$targetRegister, \"${ORIGINAL_PACKAGE_NAME}\"",
)
}
}
@Suppress("unused")
private enum class MethodCall(
override val definedClassName: String,
override val methodName: String,
override val methodParams: Array<String>,
override val returnType: String,
) : IMethodCall {
GetPackageName(
"Landroid/content/Context;",
"getPackageName",
emptyArray(),
"Ljava/lang/String;",
),
}
}

View File

@@ -13,21 +13,11 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ParamsMapPutFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplGeneralFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplLiveStreamFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplRecommendedLevelFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ScrubbedPreviewLayoutFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererDecoderRecommendedLevelFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererDecoderSpecFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererSpecFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailParentFingerprint
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
import app.revanced.util.*
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@@ -43,6 +33,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
AddResourcesPatch::class,
],
)
@Deprecated("This patch will be removed in the future.")
object SpoofSignaturePatch : BytecodePatch(
setOf(
PlayerResponseModelImplGeneralFingerprint,

View File

@@ -1,10 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object UserAgentHeaderBuilderFingerprint : MethodFingerprint(
parameters = listOf("L", "L", "L"),
opcodes = listOf(Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL),
strings = listOf("(Linux; U; Android "),
)

Some files were not shown because too many files have changed in this diff Show More