Merge branch 'dev' into revanced-extended

This commit is contained in:
inotia00 2024-10-13 02:34:39 +09:00
commit 934c33a0f9
368 changed files with 5641 additions and 1595 deletions

View File

@ -2,6 +2,8 @@
ReVanced Extended Patches. ReVanced Extended Patches.
See the [documentation](https://github.com/inotia00/revanced-documentation#readme) to learn how to apply patches and build ReVanced Extended apps.
## 📋 List of patches in this repository ## 📋 List of patches in this repository
{{ table }} {{ table }}

View File

@ -2,6 +2,8 @@
ReVanced Extended Patches. ReVanced Extended Patches.
See the [documentation](https://github.com/inotia00/revanced-documentation#readme) to learn how to apply patches and build ReVanced Extended apps.
## 📋 List of patches in this repository ## 📋 List of patches in this repository
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube) ### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)

View File

@ -1,4 +1,4 @@
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.caching = true org.gradle.caching = true
kotlin.code.style = official kotlin.code.style = official
version = 4.14.1 version = 4.14.2

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

File diff suppressed because one or more lines are too long

View File

@ -6,5 +6,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint( internal object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
parameters = listOf("L", "Ljava/lang/Object;"), parameters = listOf("L", "Ljava/lang/Object;"),
literalSupplier = { AccountSwitcherAccessibility } literalSupplier = { AccountSwitcherAccessibility },
) )

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object MenuEntryFingerprint : LiteralValueFingerprint( internal object MenuEntryFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
literalSupplier = { MenuEntry } literalSupplier = { MenuEntry },
) )

View File

@ -20,5 +20,5 @@ internal object NamesInactiveAccountThumbnailSizeFingerprint : LiteralValueFinge
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_EQZ Opcode.IF_EQZ
), ),
literalSupplier = { NamesInactiveAccountThumbnailSize } literalSupplier = { NamesInactiveAccountThumbnailSize },
) )

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object TermsOfServiceFingerprint : LiteralValueFingerprint( internal object TermsOfServiceFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
literalSupplier = { TosFooter } literalSupplier = { TosFooter },
) )

View File

@ -17,5 +17,5 @@ internal object ActionBarComponentFingerprint : LiteralValueFingerprint(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.SGET_OBJECT Opcode.SGET_OBJECT
), ),
literalSupplier = { 99180 } literalSupplier = { 99180 },
) )

View File

@ -8,5 +8,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object LikeDislikeContainerFingerprint : LiteralValueFingerprint( internal object LikeDislikeContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
literalSupplier = { LikeDislikeContainer } literalSupplier = { LikeDislikeContainer },
) )

View File

@ -2,7 +2,6 @@ package app.revanced.patches.music.ads.general
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction 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.getInstruction
import app.revanced.patches.music.ads.general.MusicAdsPatch.hookLithoFullscreenAds import app.revanced.patches.music.ads.general.MusicAdsPatch.hookLithoFullscreenAds
import app.revanced.patches.music.ads.general.MusicAdsPatch.hookNonLithoFullscreenAds import app.revanced.patches.music.ads.general.MusicAdsPatch.hookNonLithoFullscreenAds
@ -10,8 +9,6 @@ import app.revanced.patches.music.ads.general.fingerprints.AccountMenuFooterFing
import app.revanced.patches.music.ads.general.fingerprints.FloatingLayoutFingerprint import app.revanced.patches.music.ads.general.fingerprints.FloatingLayoutFingerprint
import app.revanced.patches.music.ads.general.fingerprints.GetPremiumTextViewFingerprint import app.revanced.patches.music.ads.general.fingerprints.GetPremiumTextViewFingerprint
import app.revanced.patches.music.ads.general.fingerprints.InterstitialsContainerFingerprint import app.revanced.patches.music.ads.general.fingerprints.InterstitialsContainerFingerprint
import app.revanced.patches.music.ads.general.fingerprints.MembershipSettingsFingerprint
import app.revanced.patches.music.ads.general.fingerprints.MembershipSettingsParentFingerprint
import app.revanced.patches.music.ads.general.fingerprints.NotifierShelfFingerprint import app.revanced.patches.music.ads.general.fingerprints.NotifierShelfFingerprint
import app.revanced.patches.music.ads.general.fingerprints.ShowDialogCommandFingerprint import app.revanced.patches.music.ads.general.fingerprints.ShowDialogCommandFingerprint
import app.revanced.patches.music.navigation.components.NavigationBarComponentsPatch import app.revanced.patches.music.navigation.components.NavigationBarComponentsPatch
@ -55,7 +52,6 @@ object AdsPatch : BaseBytecodePatch(
FloatingLayoutFingerprint, FloatingLayoutFingerprint,
GetPremiumTextViewFingerprint, GetPremiumTextViewFingerprint,
InterstitialsContainerFingerprint, InterstitialsContainerFingerprint,
MembershipSettingsParentFingerprint,
NotifierShelfFingerprint, NotifierShelfFingerprint,
ShowDialogCommandFingerprint ShowDialogCommandFingerprint
) )
@ -163,20 +159,6 @@ object AdsPatch : BaseBytecodePatch(
} }
} }
// premium membership menu in settings
MembershipSettingsFingerprint.resolve(
context,
MembershipSettingsParentFingerprint.resultOrThrow().classDef
)
MembershipSettingsFingerprint.resultOrThrow().mutableMethod.addInstructions(
0, """
const/4 v0, 0x0
return-object v0
"""
)
// endregion
LithoFilterPatch.addFilter(ADS_FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(ADS_FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference( SettingsPatch.addSwitchPreference(

View File

@ -17,5 +17,5 @@ internal object AccountMenuFooterFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT Opcode.IGET_OBJECT
), ),
literalSupplier = { PrivacyTosFooter } literalSupplier = { PrivacyTosFooter },
) )

View File

@ -9,5 +9,5 @@ internal object FloatingLayoutFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { FloatingLayout } literalSupplier = { FloatingLayout },
) )

View File

@ -6,5 +6,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint( internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
strings = listOf("overlay_controller_param"), strings = listOf("overlay_controller_param"),
literalSupplier = { InterstitialsContainer } literalSupplier = { InterstitialsContainer },
) )

View File

@ -1,12 +0,0 @@
package app.revanced.patches.music.ads.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MembershipSettingsParentFingerprint : MethodFingerprint(
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf("SPmanage_red")
)

View File

@ -15,6 +15,6 @@ internal object DialogSolidFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC Opcode.INVOKE_STATIC
), ),
literalSupplier = { DialogSolid } literalSupplier = { DialogSolid },
) )

View File

@ -5,6 +5,6 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object EndButtonsContainerFingerprint : LiteralValueFingerprint( internal object EndButtonsContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
literalSupplier = { EndButtonsContainer } literalSupplier = { EndButtonsContainer },
) )

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SleepTimerFingerprint : LiteralValueFingerprint( internal object SleepTimerFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45372767 } literalSupplier = { 45372767 },
) )

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object TouchOutsideFingerprint : LiteralValueFingerprint( internal object TouchOutsideFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
literalSupplier = { TouchOutside } literalSupplier = { TouchOutside },
) )

View File

@ -4,5 +4,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
object TrimSilenceConfigFingerprint : LiteralValueFingerprint( object TrimSilenceConfigFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
literalSupplier = { 45619123 } literalSupplier = { 45619123 },
) )

View File

@ -8,6 +8,6 @@ import com.android.tools.smali.dexlib2.AccessFlags
object TrimSilenceSwitchFingerprint : LiteralValueFingerprint( object TrimSilenceSwitchFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { TrimSilenceSwitch } literalSupplier = { TrimSilenceSwitch },
) )

View File

@ -9,13 +9,15 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.general.components.fingerprints.ChipCloudFingerprint import app.revanced.patches.music.general.components.fingerprints.ChipCloudFingerprint
import app.revanced.patches.music.general.components.fingerprints.ContentPillInFingerprint import app.revanced.patches.music.general.components.fingerprints.ContentPillFingerprint
import app.revanced.patches.music.general.components.fingerprints.FloatingButtonFingerprint import app.revanced.patches.music.general.components.fingerprints.FloatingButtonFingerprint
import app.revanced.patches.music.general.components.fingerprints.FloatingButtonParentFingerprint import app.revanced.patches.music.general.components.fingerprints.FloatingButtonParentFingerprint
import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemFingerprint import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemFingerprint
import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemOfflineTabFingerprint import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemOfflineTabFingerprint
import app.revanced.patches.music.general.components.fingerprints.MediaRouteButtonFingerprint import app.revanced.patches.music.general.components.fingerprints.MediaRouteButtonFingerprint
import app.revanced.patches.music.general.components.fingerprints.ParentToolMenuFingerprint
import app.revanced.patches.music.general.components.fingerprints.PlayerOverlayChipFingerprint import app.revanced.patches.music.general.components.fingerprints.PlayerOverlayChipFingerprint
import app.revanced.patches.music.general.components.fingerprints.PreferenceScreenFingerprint
import app.revanced.patches.music.general.components.fingerprints.SearchBarFingerprint import app.revanced.patches.music.general.components.fingerprints.SearchBarFingerprint
import app.revanced.patches.music.general.components.fingerprints.SearchBarParentFingerprint import app.revanced.patches.music.general.components.fingerprints.SearchBarParentFingerprint
import app.revanced.patches.music.general.components.fingerprints.SoundSearchFingerprint import app.revanced.patches.music.general.components.fingerprints.SoundSearchFingerprint
@ -26,6 +28,7 @@ import app.revanced.patches.music.general.components.fingerprints.TopBarMenuItem
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_PATH
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip
@ -57,12 +60,14 @@ object LayoutComponentsPatch : BaseBytecodePatch(
compatiblePackages = COMPATIBLE_PACKAGE, compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf( fingerprints = setOf(
ChipCloudFingerprint, ChipCloudFingerprint,
ContentPillInFingerprint, ContentPillFingerprint,
FloatingButtonParentFingerprint, FloatingButtonParentFingerprint,
HistoryMenuItemFingerprint, HistoryMenuItemFingerprint,
HistoryMenuItemOfflineTabFingerprint, HistoryMenuItemOfflineTabFingerprint,
MediaRouteButtonFingerprint, MediaRouteButtonFingerprint,
ParentToolMenuFingerprint,
PlayerOverlayChipFingerprint, PlayerOverlayChipFingerprint,
PreferenceScreenFingerprint,
SearchBarParentFingerprint, SearchBarParentFingerprint,
SoundSearchFingerprint, SoundSearchFingerprint,
TasteBuilderConstructorFingerprint, TasteBuilderConstructorFingerprint,
@ -70,9 +75,10 @@ object LayoutComponentsPatch : BaseBytecodePatch(
TopBarMenuItemImageViewFingerprint TopBarMenuItemImageViewFingerprint
) )
) { ) {
private const val INTEGRATIONS_SETTINGS_MENU_DESCRIPTOR =
"$GENERAL_PATH/SettingsMenuPatch;"
private const val CUSTOM_FILTER_CLASS_DESCRIPTOR = private const val CUSTOM_FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CustomFilter;" "$COMPONENTS_PATH/CustomFilter;"
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR = private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/LayoutComponentsFilter;" "$COMPONENTS_PATH/LayoutComponentsFilter;"
@ -194,6 +200,35 @@ object LayoutComponentsPatch : BaseBytecodePatch(
// endregion // endregion
// region patch for hide setting menus
PreferenceScreenFingerprint.resultOrThrow().mutableMethod.apply {
addInstructions(
implementation!!.instructions.lastIndex, """
invoke-virtual/range {p0 .. p0}, Lcom/google/android/apps/youtube/music/settings/fragment/SettingsHeadersFragment;->getPreferenceScreen()Landroidx/preference/PreferenceScreen;
move-result-object v0
invoke-static {v0}, $INTEGRATIONS_SETTINGS_MENU_DESCRIPTOR->hideSettingsMenu(Landroidx/preference/PreferenceScreen;)V
"""
)
}
// The lowest version supported by the patch does not have parent tool settings
ParentToolMenuFingerprint.result?.let {
it.mutableMethod.apply {
val index = it.scanResult.patternScanResult!!.startIndex + 1
val register = getInstruction<FiveRegisterInstruction>(index).registerD
addInstructions(
index, """
invoke-static {v$register}, $INTEGRATIONS_SETTINGS_MENU_DESCRIPTOR->hideParentToolsMenu(Z)Z
move-result v$register
"""
)
}
}
// endregion
// region patch for hide sound search button // region patch for hide sound search button
SoundSearchFingerprint.result?.let { SoundSearchFingerprint.result?.let {
@ -208,7 +243,7 @@ object LayoutComponentsPatch : BaseBytecodePatch(
// region patch for hide tap to update button // region patch for hide tap to update button
ContentPillInFingerprint.resultOrThrow().let { ContentPillFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
addInstructionsWithLabels( addInstructionsWithLabels(
0, 0,
@ -299,16 +334,6 @@ object LayoutComponentsPatch : BaseBytecodePatch(
"revanced_custom_filter_strings", "revanced_custom_filter_strings",
"revanced_custom_filter" "revanced_custom_filter"
) )
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_settings_menu",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.GENERAL,
"revanced_hide_settings_menu_filter_strings",
"revanced_hide_settings_menu"
)
SettingsPatch.addSwitchPreference( SettingsPatch.addSwitchPreference(
CategoryType.GENERAL, CategoryType.GENERAL,
"revanced_hide_button_shelf", "revanced_hide_button_shelf",
@ -373,5 +398,66 @@ object LayoutComponentsPatch : BaseBytecodePatch(
"revanced_hide_voice_search_button", "revanced_hide_voice_search_button",
"false" "false"
) )
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_parent_tools",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_general",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_playback",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_data_saving",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_downloads_and_storage",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_notification",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_privacy_and_location",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_recommendations",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_paid_memberships",
"true",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.SETTINGS,
"revanced_hide_settings_menu_about",
"false",
false
)
} }
} }

View File

@ -12,6 +12,6 @@ internal object ChipCloudFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { ChipCloud } literalSupplier = { ChipCloud },
) )

View File

@ -2,7 +2,7 @@ package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
internal object ContentPillInFingerprint : MethodFingerprint( internal object ContentPillFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
strings = listOf("Content pill VE is null") strings = listOf("Content pill VE is null")
) )

View File

@ -10,6 +10,6 @@ internal object FloatingButtonParentFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL, accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf(Opcode.INVOKE_DIRECT), opcodes = listOf(Opcode.INVOKE_DIRECT),
literalSupplier = { 259982244 } literalSupplier = { 259982244 },
) )

View File

@ -0,0 +1,20 @@
package app.revanced.patches.music.general.components.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 ParentToolMenuFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET,
),
strings = listOf("pref_key_parent_tools"),
customFingerprint = { methodDef, _ ->
methodDef.name == "onSettingsLoaded"
}
)

View File

@ -8,5 +8,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object PlayerOverlayChipFingerprint : LiteralValueFingerprint( internal object PlayerOverlayChipFingerprint : LiteralValueFingerprint(
returnType = "L", returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { PlayerOverlayChip } literalSupplier = { PlayerOverlayChip },
) )

View File

@ -0,0 +1,11 @@
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PreferenceScreenFingerprint : MethodFingerprint(
returnType = "V",
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/google/android/apps/youtube/music/settings/fragment/SettingsHeadersFragment;" &&
methodDef.name == "onCreatePreferences"
}
)

View File

@ -4,5 +4,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SoundSearchFingerprint : LiteralValueFingerprint( internal object SoundSearchFingerprint : LiteralValueFingerprint(
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45625491 } literalSupplier = { 45625491 },
) )

View File

@ -8,5 +8,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object TasteBuilderConstructorFingerprint : LiteralValueFingerprint( internal object TasteBuilderConstructorFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
literalSupplier = { MusicTasteBuilderShelf } literalSupplier = { MusicTasteBuilderShelf },
) )

View File

@ -9,5 +9,5 @@ internal object TooltipContentViewFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"), parameters = listOf("L"),
literalSupplier = { ToolTipContentView } literalSupplier = { ToolTipContentView },
) )

View File

@ -9,6 +9,6 @@ internal object TopBarMenuItemImageViewFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { TopBarMenuItemImageView } literalSupplier = { TopBarMenuItemImageView },
) )

View File

@ -15,6 +15,6 @@ internal object TabletIdentifierFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT Opcode.MOVE_RESULT
), ),
literalSupplier = { IsTablet } literalSupplier = { IsTablet },
) )

View File

@ -9,5 +9,5 @@ internal object BrowseIdFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"), parameters = listOf("L"),
strings = listOf("FEmusic_offline"), strings = listOf("FEmusic_offline"),
literalSupplier = { 45358178 } literalSupplier = { 45358178 },
) )

View File

@ -1,10 +1,15 @@
package app.revanced.patches.music.general.spoofappversion package app.revanced.patches.music.general.spoofappversion
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.music.general.oldstylelibraryshelf.OldStyleLibraryShelfPatch import app.revanced.patches.music.general.oldstylelibraryshelf.OldStyleLibraryShelfPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsBytecodePatch
import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.appendAppVersion
import app.revanced.util.findMethodOrThrow
import app.revanced.util.patch.BaseResourcePatch import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused") @Suppress("unused")
@ -21,6 +26,17 @@ object SpoofAppVersionPatch : BaseResourcePatch(
) { ) {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
if (SettingsPatch.upward0718) {
context.appendAppVersion("7.16.53")
SettingsBytecodePatch.contexts.findMethodOrThrow(GENERAL_CLASS_DESCRIPTOR) {
name == "getSpoofAppVersionDefault"
}.replaceInstruction(
0,
"const-string v0, \"7.16.53\""
)
}
SettingsPatch.addSwitchPreference( SettingsPatch.addSwitchPreference(
CategoryType.GENERAL, CategoryType.GENERAL,
"revanced_spoof_app_version", "revanced_spoof_app_version",

View File

@ -12,6 +12,6 @@ internal object DesignBottomSheetDialogFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { DesignBottomSheetDialog } literalSupplier = { DesignBottomSheetDialog },
) )

View File

@ -136,6 +136,7 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
"revanced_preference_screen_general", "revanced_preference_screen_general",
"revanced_preference_screen_navigation", "revanced_preference_screen_navigation",
"revanced_preference_screen_player", "revanced_preference_screen_player",
"revanced_preference_screen_settings",
"revanced_preference_screen_video", "revanced_preference_screen_video",
"revanced_preference_screen_ryd", "revanced_preference_screen_ryd",
"revanced_preference_screen_sb", "revanced_preference_screen_sb",

View File

@ -12,7 +12,7 @@ import app.revanced.patches.music.misc.backgroundplayback.fingerprints.PodCastCo
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.indexOfFirstStringInstructionOrThrow
import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
@ -52,8 +52,8 @@ object BackgroundPlaybackPatch : BaseBytecodePatch(
// don't play music video // don't play music video
MusicBrowserServiceFingerprint.resultOrThrow().let { MusicBrowserServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val stringIndex = MusicBrowserServiceFingerprint.indexOfMBSInstruction(this) val stringIndex = it.scanResult.stringsScanResult!!.matches.first().index
val targetIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) { val targetIndex = indexOfFirstInstructionOrThrow(stringIndex) {
val reference = getReference<MethodReference>() val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL && opcode == Opcode.INVOKE_VIRTUAL &&
reference?.returnType == "Z" && reference?.returnType == "Z" &&

View File

@ -8,5 +8,5 @@ internal object BackgroundPlaybackManagerFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
literalSupplier = { 64657230 } literalSupplier = { 64657230 },
) )

View File

@ -2,28 +2,14 @@ package app.revanced.patches.music.misc.backgroundplayback.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.music.misc.backgroundplayback.fingerprints.MusicBrowserServiceFingerprint.indexOfMBSInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.StringReference
internal object MusicBrowserServiceFingerprint : MethodFingerprint( internal object MusicBrowserServiceFingerprint : MethodFingerprint(
returnType = "L", returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Ljava/lang/String;", "Landroid/os/Bundle;"), parameters = listOf("Ljava/lang/String;", "Landroid/os/Bundle;"),
customFingerprint = custom@{ methodDef, _ -> strings = listOf("android.service.media.extra.RECENT"),
if (!methodDef.definingClass.endsWith("/MusicBrowserService;")) customFingerprint = { methodDef, _ ->
return@custom false methodDef.definingClass.endsWith("/MusicBrowserService;")
},
indexOfMBSInstruction(methodDef) >= 0 )
}
) {
fun indexOfMBSInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.CONST_STRING &&
getReference<StringReference>()?.string?.startsWith("MBS: Return empty root for client: %s") == true
}
}

View File

@ -8,5 +8,5 @@ internal object PodCastConfigFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45388403 } literalSupplier = { 45388403 },
) )

View File

@ -9,5 +9,5 @@ internal object BottomSheetRecyclerViewFingerprint : LiteralValueFingerprint(
returnType = "Lj${'$'}/util/Optional;", returnType = "Lj${'$'}/util/Optional;",
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL, accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { BottomSheetRecyclerView } literalSupplier = { BottomSheetRecyclerView },
) )

View File

@ -10,6 +10,6 @@ internal object TabLayoutFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
strings = listOf("FEmusic_radio_builder"), strings = listOf("FEmusic_radio_builder"),
literalSupplier = { ColorGrey } literalSupplier = { ColorGrey },
) )

View File

@ -19,6 +19,6 @@ internal object TabLayoutTextFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT Opcode.MOVE_RESULT
), ),
literalSupplier = { Text1 } literalSupplier = { Text1 },
) )

View File

@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
@ -13,6 +14,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint
import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint.AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY
import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightFingerprint import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightFingerprint
import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightParentFingerprint import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightParentFingerprint
import app.revanced.patches.music.player.components.fingerprints.HandleSearchRenderedFingerprint import app.revanced.patches.music.player.components.fingerprints.HandleSearchRenderedFingerprint
@ -35,19 +37,17 @@ import app.revanced.patches.music.player.components.fingerprints.PlayerViewPager
import app.revanced.patches.music.player.components.fingerprints.QuickSeekOverlayFingerprint import app.revanced.patches.music.player.components.fingerprints.QuickSeekOverlayFingerprint
import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint
import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint import app.revanced.patches.music.player.components.fingerprints.ShuffleOnClickFingerprint
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction
import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint
import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint
import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFingerprint import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFingerprint
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH
import app.revanced.patches.music.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.AudioVideoSwitchToggle
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.DarkBackground import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.DarkBackground
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton
@ -61,6 +61,7 @@ import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.util.addStaticFieldToIntegration
import app.revanced.util.alsoResolve import app.revanced.util.alsoResolve
import app.revanced.util.findMethodOrThrow import app.revanced.util.findMethodOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
@ -73,11 +74,10 @@ import app.revanced.util.injectLiteralInstructionBooleanCall
import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.injectLiteralInstructionViewCall
import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import app.revanced.util.transformFields import app.revanced.util.transformMethods
import app.revanced.util.traverseClassHierarchy import app.revanced.util.traverseClassHierarchy
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.MethodParameter import com.android.tools.smali.dexlib2.iface.MethodParameter
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction 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.OneRegisterInstruction
@ -88,7 +88,6 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.util.MethodUtil
import kotlin.properties.Delegates import kotlin.properties.Delegates
@Suppress("unused", "LocalVariableName") @Suppress("unused", "LocalVariableName")
@ -101,7 +100,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
PlayerComponentsResourcePatch::class, PlayerComponentsResourcePatch::class,
SettingsPatch::class, SettingsPatch::class,
SharedResourceIdPatch::class, SharedResourceIdPatch::class,
VideoTypeHookPatch::class VideoTypeHookPatch::class,
), ),
compatiblePackages = COMPATIBLE_PACKAGE, compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf( fingerprints = setOf(
@ -126,13 +125,16 @@ object PlayerComponentsPatch : BaseBytecodePatch(
QuickSeekOverlayFingerprint, QuickSeekOverlayFingerprint,
RemixGenericButtonFingerprint, RemixGenericButtonFingerprint,
RepeatTrackFingerprint, RepeatTrackFingerprint,
ShuffleClassReferenceFingerprint, ShuffleOnClickFingerprint,
SwipeToCloseFingerprint, SwipeToCloseFingerprint,
) )
) { ) {
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/PlayerComponentsFilter;" "$COMPONENTS_PATH/PlayerComponentsFilter;"
private const val INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR =
"$INTEGRATIONS_PATH/utils/VideoUtils;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// region patch for disable gesture in player // region patch for disable gesture in player
@ -628,14 +630,25 @@ object PlayerComponentsPatch : BaseBytecodePatch(
// region patch for hide audio video switch toggle // region patch for hide audio video switch toggle
AudioVideoSwitchToggleFingerprint.resultOrThrow().mutableMethod.apply { AudioVideoSwitchToggleFingerprint.resultOrThrow().mutableMethod.apply {
val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AudioVideoSwitchToggle) implementation!!.instructions
val viewIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) .withIndex()
val viewRegister = getInstruction<OneRegisterInstruction>(viewIndex).registerA .filter { (_, instruction) ->
val reference = (instruction as? ReferenceInstruction)?.reference
instruction.opcode == Opcode.INVOKE_VIRTUAL &&
reference is MethodReference &&
reference.toString() == AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY
}
.map { (index, _) -> index }
.reversed()
.forEach { index ->
val instruction = getInstruction<FiveRegisterInstruction>(index)
addInstruction( replaceInstruction(
viewIndex + 1, index,
"invoke-static {v$viewRegister}, $PLAYER_CLASS_DESCRIPTOR->hideAudioVideoSwitchToggle(Landroid/view/View;)V" "invoke-static {v${instruction.registerC}, v${instruction.registerD}}," +
) "$PLAYER_CLASS_DESCRIPTOR->hideAudioVideoSwitchToggle(Landroid/view/View;I)V"
)
}
} }
SettingsPatch.addSwitchPreference( SettingsPatch.addSwitchPreference(
@ -735,154 +748,87 @@ object PlayerComponentsPatch : BaseBytecodePatch(
// region patch for remember shuffle state // region patch for remember shuffle state
val MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR = ShuffleOnClickFingerprint.resultOrThrow().mutableMethod.apply {
"Lcom/google/android/apps/youtube/music/watchpage/MusicPlaybackControls;" val accessibilityIndex =
ShuffleOnClickFingerprint.indexOfAccessibilityInstruction(this)
lateinit var rememberShuffleStateObjectClass: String // region set shuffle enum
lateinit var rememberShuffleStateImageViewReference: Reference
lateinit var rememberShuffleStateShuffleStateLabel: String
ShuffleClassReferenceFingerprint.resultOrThrow().let { val enumIndex = indexOfFirstInstructionReversedOrThrow(accessibilityIndex) {
it.mutableMethod.apply { opcode == Opcode.INVOKE_DIRECT &&
rememberShuffleStateObjectClass = definingClass getReference<MethodReference>()?.returnType == "Ljava/lang/String;"
val imageViewIndex = indexOfImageViewInstruction(this)
val ordinalIndex = indexOfOrdinalInstruction(this)
val invokeInterfaceIndex =
indexOfFirstInstructionReversedOrThrow(ordinalIndex, Opcode.INVOKE_INTERFACE)
val iGetObjectIndex =
indexOfFirstInstructionReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT)
val checkCastIndex =
indexOfFirstInstructionOrThrow(invokeInterfaceIndex, Opcode.CHECK_CAST)
val iGetObjectReference =
getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
val invokeInterfaceReference =
getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference
val checkCastReference =
getInstruction<ReferenceInstruction>(checkCastIndex).reference
val getOrdinalClassReference =
getInstruction<ReferenceInstruction>(checkCastIndex + 1).reference
val ordinalReference =
getInstruction<ReferenceInstruction>(ordinalIndex).reference
rememberShuffleStateImageViewReference =
getInstruction<ReferenceInstruction>(imageViewIndex).reference
rememberShuffleStateShuffleStateLabel = """
iget-object v1, v0, $iGetObjectReference
invoke-interface {v1}, $invokeInterfaceReference
move-result-object v1
check-cast v1, $checkCastReference
"""
rememberShuffleStateShuffleStateLabel += if (getInstruction(checkCastIndex + 1).opcode == Opcode.INVOKE_VIRTUAL) {
// YouTube Music 7.16.53+
"""
invoke-virtual {v1}, $getOrdinalClassReference
move-result-object v1
""".trimIndent()
} else {
"""
iget-object v1, v1, $getOrdinalClassReference
""".trimIndent()
}
rememberShuffleStateShuffleStateLabel += """
invoke-virtual {v1}, $ordinalReference
move-result v1
""".trimIndent()
} }
val enumRegister = getInstruction<FiveRegisterInstruction>(enumIndex).registerD
val enumClass =
(getInstruction<ReferenceInstruction>(enumIndex).reference as MethodReference).parameterTypes.first()
val constructorMethod = addInstruction(
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) } enumIndex,
val onClickMethod = it.mutableClass.methods.first { method -> method.name == "onClick" } "invoke-static {v$enumRegister}, $PLAYER_CLASS_DESCRIPTOR->setShuffleState(Ljava/lang/Enum;)V"
)
constructorMethod.apply { // endregion
addInstruction(
implementation!!.instructions.lastIndex,
"sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass"
)
}
onClickMethod.apply { // region set static field
addInstructions(
0, """
move-object v0, p0
""" + rememberShuffleStateShuffleStateLabel + """
invoke-static {v1}, $PLAYER_CLASS_DESCRIPTOR->setShuffleState(I)V
"""
)
}
context.traverseClassHierarchy(it.mutableClass) { val shuffleClassIndex =
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL indexOfFirstInstructionReversedOrThrow(accessibilityIndex, Opcode.CHECK_CAST)
transformFields { val shuffleClass =
ImmutableField( getInstruction<ReferenceInstruction>(shuffleClassIndex).reference.toString()
val shuffleMutableClass = context.findClass { classDef ->
classDef.type == shuffleClass
}!!.mutableClass
val shuffleMethod = shuffleMutableClass.methods.find { method ->
method.parameterTypes.firstOrNull() == enumClass &&
method.parameterTypes.size == 1 &&
method.returnType == "V"
} ?: throw PatchException("target not found")
val smaliInstructions =
"""
if-eqz v0, :ignore
sget-object v1, $enumClass->b:$enumClass
invoke-virtual {v0, v1}, $shuffleClass->${shuffleMethod.name}($enumClass)V
:ignore
return-void
"""
context.addStaticFieldToIntegration(
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR,
"shuffleTracks",
"shuffleClass",
shuffleClass,
smaliInstructions
)
// endregion
// region make all methods accessible
context.traverseClassHierarchy(shuffleMutableClass) {
transformMethods {
ImmutableMethod(
definingClass, definingClass,
name, name,
type, parameters,
AccessFlags.PUBLIC or AccessFlags.PUBLIC, returnType,
null, AccessFlags.PUBLIC or AccessFlags.FINAL,
annotations, annotations,
null hiddenApiRestrictions,
implementation
).toMutable() ).toMutable()
} }
} }
// endregion
} }
MusicPlaybackControlsFingerprint.resultOrThrow().let { MusicPlaybackControlsFingerprint.resultOrThrow().mutableMethod.addInstruction(
it.mutableMethod.apply { 0,
addInstruction( "invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->shuffleTracks()V"
0, )
"invoke-virtual {v0}, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->rememberShuffleState()V"
)
val shuffleField = ImmutableField(
definingClass,
"shuffleClass",
rememberShuffleStateObjectClass,
AccessFlags.PUBLIC or AccessFlags.STATIC,
null,
annotations,
null
).toMutable()
val shuffleMethod = ImmutableMethod(
definingClass,
"rememberShuffleState",
emptyList(),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
annotations, null,
MutableMethodImplementation(5)
).toMutable()
shuffleMethod.addInstructionsWithLabels(
0, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->getShuffleState()I
move-result v2
if-nez v2, :dont_shuffle
sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass
""" + rememberShuffleStateShuffleStateLabel + """
iget-object v3, v0, $rememberShuffleStateImageViewReference
if-eqz v3, :dont_shuffle
invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z
if-eqz v1, :dont_shuffle
invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z
:dont_shuffle
return-void
"""
)
it.mutableClass.methods.add(shuffleMethod)
it.mutableClass.staticFields.add(shuffleField)
}
}
SettingsPatch.addSwitchPreference( SettingsPatch.addSwitchPreference(
CategoryType.PLAYER, CategoryType.PLAYER,

View File

@ -1,12 +1,25 @@
package app.revanced.patches.music.player.components.fingerprints package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.AudioVideoSwitchToggle import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint.AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object AudioVideoSwitchToggleFingerprint : LiteralValueFingerprint( internal object AudioVideoSwitchToggleFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { AudioVideoSwitchToggle } parameters = emptyList(),
) customFingerprint = { methodDef, _ ->
methodDef.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.toString() == AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY
} >= 0
}
) {
const val AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY =
"Lcom/google/android/apps/youtube/music/player/AudioVideoSwitcherToggleView;->setVisibility(I)V"
}

View File

@ -11,7 +11,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object EngagementPanelHeightFingerprint : MethodFingerprint( internal object EngagementPanelHeightFingerprint : MethodFingerprint(
returnType = "L", returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
// In YouTube Music 7.21.50+, there are two methods with similar structure, so this Opcode pattern must be used.
opcodes = listOf( opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,

View File

@ -11,5 +11,5 @@ internal object MiniPlayerDefaultTextFingerprint : LiteralValueFingerprint(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IF_NE Opcode.IF_NE
), ),
literalSupplier = { MiniPlayerDefaultText } literalSupplier = { MiniPlayerDefaultText },
) )

View File

@ -9,5 +9,5 @@ internal object MiniPlayerParentFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { MiniPlayerMdxPlaying } literalSupplier = { MiniPlayerMdxPlaying },
) )

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object OldEngagementPanelFingerprint : LiteralValueFingerprint( internal object OldEngagementPanelFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45427672 } literalSupplier = { 45427672 },
) )

View File

@ -8,5 +8,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object OldPlayerBackgroundFingerprint : LiteralValueFingerprint( internal object OldPlayerBackgroundFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45415319 } literalSupplier = { 45415319 },
) )

View File

@ -8,5 +8,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object OldPlayerLayoutFingerprint : LiteralValueFingerprint( internal object OldPlayerLayoutFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45399578 } literalSupplier = { 45399578 },
) )

View File

@ -15,5 +15,5 @@ internal object RemixGenericButtonFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.FLOAT_TO_INT Opcode.FLOAT_TO_INT
), ),
literalSupplier = { RemixGenericButtonSize } literalSupplier = { RemixGenericButtonSize },
) )

View File

@ -1,40 +0,0 @@
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.YtFillArrowShuffle
import app.revanced.util.containsWideLiteralInstructionValue
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object ShuffleClassReferenceFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf("Unknown shuffle mode"),
customFingerprint = { methodDef, _ ->
methodDef.containsWideLiteralInstructionValue(YtFillArrowShuffle) &&
indexOfOrdinalInstruction(methodDef) >= 0 &&
indexOfImageViewInstruction(methodDef) >= 0
}
) {
fun indexOfOrdinalInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "ordinal"
}
fun indexOfImageViewInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.IGET_OBJECT &&
getReference<FieldReference>()?.type == "Landroid/widget/ImageView;"
}
}

View File

@ -0,0 +1,30 @@
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.music.player.components.fingerprints.ShuffleOnClickFingerprint.indexOfAccessibilityInstruction
import app.revanced.util.containsWideLiteralInstructionValue
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object ShuffleOnClickFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/view/View;"),
customFingerprint = { methodDef, _ ->
methodDef.containsWideLiteralInstructionValue(45468) &&
methodDef.name == "onClick" &&
indexOfAccessibilityInstruction(methodDef) >= 0
}
) {
fun indexOfAccessibilityInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "announceForAccessibility"
}
}

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SwipeToCloseFingerprint : LiteralValueFingerprint( internal object SwipeToCloseFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { 45398432 } literalSupplier = { 45398432 },
) )

View File

@ -10,5 +10,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object HeaderSwitchConfigFingerprint : LiteralValueFingerprint( internal object HeaderSwitchConfigFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { 45617851 } literalSupplier = { 45617851 },
) )

View File

@ -6,8 +6,8 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal object PlaybackRateBottomSheetClassFingerprint : LiteralValueFingerprint( internal object PlaybackRateBottomSheetClassFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { VarispeedUnavailableTitle } literalSupplier = { VarispeedUnavailableTitle },
) )

View File

@ -8,7 +8,6 @@ import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId
import app.revanced.patches.shared.mapping.ResourceType.BOOL import app.revanced.patches.shared.mapping.ResourceType.BOOL
import app.revanced.patches.shared.mapping.ResourceType.COLOR import app.revanced.patches.shared.mapping.ResourceType.COLOR
import app.revanced.patches.shared.mapping.ResourceType.DIMEN import app.revanced.patches.shared.mapping.ResourceType.DIMEN
import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE
import app.revanced.patches.shared.mapping.ResourceType.ID import app.revanced.patches.shared.mapping.ResourceType.ID
import app.revanced.patches.shared.mapping.ResourceType.LAYOUT import app.revanced.patches.shared.mapping.ResourceType.LAYOUT
import app.revanced.patches.shared.mapping.ResourceType.STRING import app.revanced.patches.shared.mapping.ResourceType.STRING
@ -17,7 +16,6 @@ import app.revanced.patches.shared.mapping.ResourceType.STYLE
@Patch(dependencies = [ResourceMappingPatch::class]) @Patch(dependencies = [ResourceMappingPatch::class])
object SharedResourceIdPatch : ResourcePatch() { object SharedResourceIdPatch : ResourcePatch() {
var AccountSwitcherAccessibility = -1L var AccountSwitcherAccessibility = -1L
var AudioVideoSwitchToggle = -1L
var BottomSheetRecyclerView = -1L var BottomSheetRecyclerView = -1L
var ButtonContainer = -1L var ButtonContainer = -1L
var ButtonIconPaddingMedium = -1L var ButtonIconPaddingMedium = -1L
@ -59,12 +57,10 @@ object SharedResourceIdPatch : ResourcePatch() {
var TouchOutside = -1L var TouchOutside = -1L
var TrimSilenceSwitch: Long = -1 var TrimSilenceSwitch: Long = -1
var VarispeedUnavailableTitle = -1L var VarispeedUnavailableTitle = -1L
var YtFillArrowShuffle = -1L
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
AccountSwitcherAccessibility = getId(STRING, "account_switcher_accessibility_label") AccountSwitcherAccessibility = getId(STRING, "account_switcher_accessibility_label")
AudioVideoSwitchToggle = getId(ID, "audio_video_switch_toggle")
BottomSheetRecyclerView = getId(LAYOUT, "bottom_sheet_recycler_view") BottomSheetRecyclerView = getId(LAYOUT, "bottom_sheet_recycler_view")
ButtonContainer = getId(ID, "button_container") ButtonContainer = getId(ID, "button_container")
ButtonIconPaddingMedium = getId(DIMEN, "button_icon_padding_medium") ButtonIconPaddingMedium = getId(DIMEN, "button_icon_padding_medium")
@ -106,7 +102,6 @@ object SharedResourceIdPatch : ResourcePatch() {
TouchOutside = getId(ID, "touch_outside") TouchOutside = getId(ID, "touch_outside")
TrimSilenceSwitch = getId(ID, "trim_silence_switch") TrimSilenceSwitch = getId(ID, "trim_silence_switch")
VarispeedUnavailableTitle = getId(STRING, "varispeed_unavailable_title") VarispeedUnavailableTitle = getId(STRING, "varispeed_unavailable_title")
YtFillArrowShuffle = getId(DRAWABLE, "yt_fill_arrow_shuffle_vd_theme_24")
} }
} }

View File

@ -7,5 +7,5 @@ import com.android.tools.smali.dexlib2.Opcode
internal object TextComponentFingerprint : LiteralValueFingerprint( internal object TextComponentFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
opcodes = listOf(Opcode.CONST_HIGH16), opcodes = listOf(Opcode.CONST_HIGH16),
literalSupplier = { ButtonIconPaddingMedium } literalSupplier = { ButtonIconPaddingMedium },
) )

View File

@ -8,6 +8,7 @@ enum class CategoryType(val value: String, var added: Boolean) {
GENERAL("general", false), GENERAL("general", false),
NAVIGATION("navigation", false), NAVIGATION("navigation", false),
PLAYER("player", false), PLAYER("player", false),
SETTINGS("settings", false),
VIDEO("video", false), VIDEO("video", false),
RETURN_YOUTUBE_DISLIKE("ryd", false), RETURN_YOUTUBE_DISLIKE("ryd", false),
SPONSOR_BLOCK("sb", false), SPONSOR_BLOCK("sb", false),

View File

@ -44,8 +44,10 @@ object SettingsBytecodePatch : BytecodePatch(
"$INTEGRATIONS_PATH/settings/preference/ReVancedPreferenceFragment;" "$INTEGRATIONS_PATH/settings/preference/ReVancedPreferenceFragment;"
private const val INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR = private const val INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR =
"$UTILS_PATH/InitializationPatch;" "$UTILS_PATH/InitializationPatch;"
lateinit var contexts: BytecodeContext
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
contexts = context
/** /**
* Set SharedPrefCategory * Set SharedPrefCategory

View File

@ -5,5 +5,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SeekBarConstructorFingerprint : LiteralValueFingerprint( internal object SeekBarConstructorFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
literalSupplier = { InlineTimeBarAdBreakMarkerColor } literalSupplier = { InlineTimeBarAdBreakMarkerColor },
) )

View File

@ -11,5 +11,5 @@ internal object VideoQualityListFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.RETURN_VOID Opcode.RETURN_VOID
), ),
literalSupplier = { QualityAuto } literalSupplier = { QualityAuto },
) )

View File

@ -19,5 +19,5 @@ internal object MusicAdsFingerprint : LiteralValueFingerprint(
Opcode.IPUT_WIDE, Opcode.IPUT_WIDE,
Opcode.CONST_4, Opcode.CONST_4,
), ),
literalSupplier = { 4 } literalSupplier = { 4 },
) )

View File

@ -96,17 +96,20 @@ object LithoFilterPatch : BytecodePatch(
} }
.map { (index, _) -> index } .map { (index, _) -> index }
.reversed() .reversed()
.forEach { .forEach { index ->
val insertRegister = val insertInstruction = getInstruction(index + 1)
getInstruction<OneRegisterInstruction>(it + 1).registerA if (insertInstruction is OneRegisterInstruction) {
val insertIndex = it + 2 val insertRegister =
insertInstruction.registerA
val insertIndex = index + 2
addInstructionsWithLabels( addInstructionsWithLabels(
insertIndex, """ insertIndex, """
if-nez v$insertRegister, :ignore if-nez v$insertRegister, :ignore
""" + emptyComponentLabel, """ + emptyComponentLabel,
ExternalLabel("ignore", getInstruction(insertIndex)) ExternalLabel("ignore", getInstruction(insertIndex))
) )
}
} }
emptyComponentLabel = """ emptyComponentLabel = """

View File

@ -1,42 +1,43 @@
package app.revanced.patches.shared.settingmenu package app.revanced.patches.shared.settingmenu
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH
import app.revanced.patches.shared.settingmenu.fingerprints.SettingsMenuFingerprint import app.revanced.patches.shared.settingmenu.fingerprints.FindPreferenceFingerprint
import app.revanced.patches.shared.viewgroup.ViewGroupMarginLayoutParamsHookPatch import app.revanced.patches.shared.settingmenu.fingerprints.RemovePreferenceFingerprint
import app.revanced.util.getReference import app.revanced.util.findMethodOrThrow
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.getMethodCall
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch( @Patch(
description = "Hide the settings menu for YouTube or YouTube Music.", description = "Hide the settings menu for YouTube or YouTube Music.",
dependencies = [ViewGroupMarginLayoutParamsHookPatch::class]
) )
object SettingsMenuPatch : BytecodePatch( object SettingsMenuPatch : BytecodePatch(
setOf(SettingsMenuFingerprint) setOf(
FindPreferenceFingerprint,
RemovePreferenceFingerprint
)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"$PATCHES_PATH/SettingsMenuPatch;" "$PATCHES_PATH/BaseSettingsMenuPatch;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SettingsMenuFingerprint.resultOrThrow().mutableMethod.apply { val findPreferenceMethodCall = FindPreferenceFingerprint.getMethodCall()
val insertIndex = indexOfFirstInstructionOrThrow { val removePreferenceMethodCall = RemovePreferenceFingerprint.getMethodCall()
getReference<FieldReference>()?.type == "Landroid/support/v7/widget/RecyclerView;"
}
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstruction( context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
insertIndex, name == "removePreference"
"invoke-static {v$insertRegister}, " + }.addInstructionsWithLabels(
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideSettingsMenu(Landroid/support/v7/widget/RecyclerView;)V" 0, """
) invoke-virtual {p0, p1}, $findPreferenceMethodCall
} move-result-object v0
if-eqz v0, :ignore
invoke-virtual {p0, v0}, $removePreferenceMethodCall
:ignore
return-void
"""
)
} }
} }

View File

@ -0,0 +1,15 @@
package app.revanced.patches.shared.settingmenu.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object FindPreferenceFingerprint : MethodFingerprint(
returnType = "Landroidx/preference/Preference;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Ljava/lang/CharSequence;"),
strings = listOf("Key cannot be null"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Landroidx/preference/PreferenceGroup;"
}
)

View File

@ -0,0 +1,19 @@
package app.revanced.patches.shared.settingmenu.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 RemovePreferenceFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroidx/preference/Preference;"),
opcodes = listOf(Opcode.INVOKE_VIRTUAL),
customFingerprint = custom@{ methodDef, _ ->
if (methodDef.definingClass != "Landroidx/preference/PreferenceGroup;") {
return@custom false
}
val instructions = methodDef.implementation?.instructions ?: return@custom false
instructions.elementAt(0).opcode == Opcode.INVOKE_DIRECT
}
)

View File

@ -1,8 +0,0 @@
package app.revanced.patches.shared.settingmenu.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SettingsMenuFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
literalSupplier = { 16908351 }
)

View File

@ -0,0 +1,135 @@
package app.revanced.patches.shared.textcomponent
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.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.textcomponent.fingerprints.SpannableStringBuilderFingerprint
import app.revanced.patches.shared.textcomponent.fingerprints.TextComponentConstructorFingerprint
import app.revanced.patches.shared.textcomponent.fingerprints.TextComponentContextFingerprint
import app.revanced.util.alsoResolve
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
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.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
object TextComponentPatch : BytecodePatch(
setOf(
SpannableStringBuilderFingerprint,
TextComponentConstructorFingerprint,
)
) {
override fun execute(context: BytecodeContext) {
SpannableStringBuilderFingerprint.resultOrThrow().mutableMethod.apply {
spannedMethod = this
spannedIndex = SpannableStringBuilderFingerprint.indexOfSpannableStringInstruction(this)
spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
spannedContextRegister =
getInstruction<TwoRegisterInstruction>(0).registerA
replaceInstruction(
spannedIndex,
"nop"
)
addInstruction(
++spannedIndex,
"invoke-static {v$spannedRegister}, ${SpannableStringBuilderFingerprint.SPANNABLE_STRING_REFERENCE}"
)
}
TextComponentContextFingerprint.alsoResolve(
context, TextComponentConstructorFingerprint
).let {
it.mutableMethod.apply {
textComponentMethod = this
val conversionContextFieldIndex = indexOfFirstInstructionOrThrow {
getReference<FieldReference>()?.type == "Ljava/util/Map;"
} - 1
val conversionContextFieldReference =
getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference
// ~ YouTube 19.32.xx
val legacyCharSequenceIndex = indexOfFirstInstruction {
getReference<FieldReference>()?.type == "Ljava/util/BitSet;"
} - 1
val charSequenceIndex = indexOfFirstInstruction {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL &&
reference?.returnType == "V" &&
reference.parameterTypes.firstOrNull() == "Ljava/lang/CharSequence;"
}
val insertIndex: Int
if (legacyCharSequenceIndex > -2) {
textComponentRegister =
getInstruction<TwoRegisterInstruction>(legacyCharSequenceIndex).registerA
insertIndex = legacyCharSequenceIndex - 1
} else if (charSequenceIndex > -1) {
textComponentRegister =
getInstruction<FiveRegisterInstruction>(charSequenceIndex).registerD
insertIndex = charSequenceIndex
} else {
throw PatchException("Could not find insert index")
}
textComponentContextRegister = getInstruction<TwoRegisterInstruction>(
indexOfFirstInstructionOrThrow(insertIndex, Opcode.IGET_OBJECT)
).registerA
addInstructions(
insertIndex, """
move-object/from16 v$textComponentContextRegister, p0
iget-object v$textComponentContextRegister, v$textComponentContextRegister, $conversionContextFieldReference
"""
)
textComponentIndex = insertIndex + 2
}
}
}
private lateinit var spannedMethod: MutableMethod
private var spannedIndex = 0
private var spannedRegister = 0
private var spannedContextRegister = 0
private lateinit var textComponentMethod: MutableMethod
private var textComponentIndex = 0
private var textComponentRegister = 0
private var textComponentContextRegister = 0
fun hookSpannableString(
classDescriptor: String,
methodName: String
) = spannedMethod.addInstructions(
spannedIndex, """
invoke-static {v$spannedContextRegister, v$spannedRegister}, $classDescriptor->$methodName(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$spannedRegister
"""
)
fun hookTextComponent(
classDescriptor: String,
methodName: String = "onLithoTextLoaded"
) = textComponentMethod.apply {
addInstructions(
textComponentIndex, """
invoke-static {v$textComponentContextRegister, v$textComponentRegister}, $classDescriptor->$methodName(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$textComponentRegister
"""
)
textComponentIndex += 2
}
}

View File

@ -0,0 +1,26 @@
package app.revanced.patches.shared.textcomponent.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.shared.textcomponent.fingerprints.SpannableStringBuilderFingerprint.indexOfSpannableStringInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object SpannableStringBuilderFingerprint : MethodFingerprint(
returnType = "Ljava/lang/CharSequence;",
strings = listOf("Failed to set PB Style Run Extension in TextComponentSpec. Extension id: %s"),
customFingerprint = { methodDef, _ ->
indexOfSpannableStringInstruction(methodDef) >= 0
}
) {
const val SPANNABLE_STRING_REFERENCE =
"Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;"
fun indexOfSpannableStringInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC &&
getReference<MethodReference>()?.toString() == SPANNABLE_STRING_REFERENCE
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints package app.revanced.patches.shared.textcomponent.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints package app.revanced.patches.shared.textcomponent.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -6,5 +6,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint( internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
strings = listOf("overlay_controller_param"), strings = listOf("overlay_controller_param"),
literalSupplier = { InterstitialsContainer } literalSupplier = { InterstitialsContainer },
) )

View File

@ -18,6 +18,7 @@ import app.revanced.patches.youtube.feed.components.fingerprints.ChannelListSubM
import app.revanced.patches.youtube.feed.components.fingerprints.ChannelListSubMenuTabletSyntheticFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ChannelListSubMenuTabletSyntheticFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabBuilderFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabBuilderFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabRendererFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabRendererFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.ContentPillFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserParentFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserParentFingerprint
import app.revanced.patches.youtube.feed.components.fingerprints.EngagementPanelUpdateFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.EngagementPanelUpdateFingerprint
@ -37,8 +38,13 @@ import app.revanced.patches.youtube.utils.integrations.Constants.FEED_PATH
import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Bar
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CaptionToggleContainer import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CaptionToggleContainer
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ChannelListSubMenu
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ContentPill
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.HorizontalCardList
import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.util.alsoResolve import app.revanced.util.alsoResolve
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod import app.revanced.util.getWalkerMethod
@ -46,6 +52,7 @@ import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow
import app.revanced.util.injectLiteralInstructionViewCall
import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -78,6 +85,7 @@ object FeedComponentsPatch : BaseBytecodePatch(
ChannelListSubMenuTabletFingerprint, ChannelListSubMenuTabletFingerprint,
ChannelListSubMenuTabletSyntheticFingerprint, ChannelListSubMenuTabletSyntheticFingerprint,
ChannelTabRendererFingerprint, ChannelTabRendererFingerprint,
ContentPillFingerprint,
ElementParserParentFingerprint, ElementParserParentFingerprint,
EngagementPanelBuilderFingerprint, EngagementPanelBuilderFingerprint,
FilterBarHeightFingerprint, FilterBarHeightFingerprint,
@ -106,23 +114,35 @@ object FeedComponentsPatch : BaseBytecodePatch(
// region patch for hide carousel shelf, subscriptions channel section, latest videos button // region patch for hide carousel shelf, subscriptions channel section, latest videos button
mapOf( listOf(
BreakingNewsFingerprint to "hideBreakingNewsShelf", // carousel shelf, only used to tablet layout. // carousel shelf, only used to tablet layout.
ChannelListSubMenuFingerprint to "hideSubscriptionsChannelSection", // subscriptions channel section Triple(
LatestVideosButtonFingerprint to "hideLatestVideosButton", // latest videos button BreakingNewsFingerprint,
).forEach { (fingerprint, methodName) -> "hideBreakingNewsShelf",
fingerprint.resultOrThrow().let { HorizontalCardList
it.mutableMethod.apply { ),
val targetIndex = it.scanResult.patternScanResult!!.endIndex // subscriptions channel section.
val targetRegister = Triple(
getInstruction<OneRegisterInstruction>(targetIndex).registerA ChannelListSubMenuFingerprint,
"hideSubscriptionsChannelSection",
addInstruction( ChannelListSubMenu
targetIndex + 1, ),
"invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V" // latest videos button
) Triple(
} ContentPillFingerprint,
} "hideLatestVideosButton",
ContentPill
),
Triple(
LatestVideosButtonFingerprint,
"hideLatestVideosButton",
Bar
),
).forEach { (fingerprint, methodName, literal) ->
val smaliInstruction = """
invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $FEED_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V
"""
fingerprint.injectLiteralInstructionViewCall(literal, smaliInstruction)
} }
// endregion // endregion

View File

@ -4,15 +4,8 @@ import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.HorizontalCardList import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.HorizontalCardList
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object BreakingNewsFingerprint : LiteralValueFingerprint( internal object BreakingNewsFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
opcodes = listOf( literalSupplier = { HorizontalCardList },
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
literalSupplier = { HorizontalCardList }
) )

View File

@ -9,5 +9,5 @@ internal object CaptionsButtonFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literalSupplier = { CaptionToggleContainer } literalSupplier = { CaptionToggleContainer },
) )

View File

@ -9,5 +9,5 @@ internal object CaptionsButtonSyntheticFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;", returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC,
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
literalSupplier = { CaptionToggleContainer } literalSupplier = { CaptionToggleContainer },
) )

View File

@ -2,14 +2,7 @@ package app.revanced.patches.youtube.feed.components.fingerprints
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ChannelListSubMenu import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ChannelListSubMenu
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object ChannelListSubMenuFingerprint : LiteralValueFingerprint( internal object ChannelListSubMenuFingerprint : LiteralValueFingerprint(
opcodes = listOf( literalSupplier = { ChannelListSubMenu },
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
literalSupplier = { ChannelListSubMenu }
) )

View File

@ -6,8 +6,8 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal object ChannelListSubMenuTabletFingerprint : LiteralValueFingerprint( internal object ChannelListSubMenuTabletFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
returnType = "V", literalSupplier = { DrawerResults },
literalSupplier = { DrawerResults }
) )

View File

@ -0,0 +1,13 @@
package app.revanced.patches.youtube.feed.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ContentPill
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object ContentPillFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L", "Z"),
literalSupplier = { ContentPill },
)

View File

@ -15,5 +15,5 @@ internal object FilterBarHeightFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IPUT Opcode.IPUT
), ),
literalSupplier = { FilterBarHeight } literalSupplier = { FilterBarHeight },
) )

View File

@ -4,17 +4,10 @@ import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Bar import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Bar
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object LatestVideosButtonFingerprint : LiteralValueFingerprint( internal object LatestVideosButtonFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L", "Z"), parameters = listOf("L", "Z"),
opcodes = listOf( literalSupplier = { Bar },
Opcode.CONST,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
literalSupplier = { Bar }
) )

View File

@ -14,5 +14,5 @@ internal object RelatedChipCloudFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { RelatedChipCloudMargin } literalSupplier = { RelatedChipCloudMargin },
) )

View File

@ -16,5 +16,5 @@ internal object SearchResultsChipBarFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { BarContainerHeight } literalSupplier = { BarContainerHeight },
) )

View File

@ -11,5 +11,5 @@ internal object ShowMoreButtonFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { ExpandButtonDown } literalSupplier = { ExpandButtonDown },
) )

View File

@ -7,9 +7,9 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal object ContextualMenuItemBuilderFingerprint : LiteralValueFingerprint( internal object ContextualMenuItemBuilderFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.SYNTHETIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.SYNTHETIC,
parameters = listOf("L", "L"), parameters = listOf("L", "L"),
returnType = "V",
opcodes = listOf( opcodes = listOf(
Opcode.CHECK_CAST, Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
@ -17,5 +17,5 @@ internal object ContextualMenuItemBuilderFingerprint : LiteralValueFingerprint(
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.ADD_INT_2ADDR Opcode.ADD_INT_2ADDR
), ),
literalSupplier = { PosterArtWidthDefault } literalSupplier = { PosterArtWidthDefault },
) )

View File

@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.shared.litho.LithoFilterPatch
@ -19,11 +20,13 @@ import app.revanced.patches.youtube.general.components.fingerprints.AppBlockingC
import app.revanced.patches.youtube.general.components.fingerprints.BottomUiContainerFingerprint import app.revanced.patches.youtube.general.components.fingerprints.BottomUiContainerFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.FloatingMicrophoneFingerprint import app.revanced.patches.youtube.general.components.fingerprints.FloatingMicrophoneFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.PiPNotificationFingerprint import app.revanced.patches.youtube.general.components.fingerprints.PiPNotificationFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.PreferenceScreenFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.TooltipContentFullscreenFingerprint import app.revanced.patches.youtube.general.components.fingerprints.TooltipContentFullscreenFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.TooltipContentViewFingerprint import app.revanced.patches.youtube.general.components.fingerprints.TooltipContentViewFingerprint
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility
import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch
@ -60,10 +63,13 @@ object LayoutComponentsPatch : BaseBytecodePatch(
BottomUiContainerFingerprint, BottomUiContainerFingerprint,
FloatingMicrophoneFingerprint, FloatingMicrophoneFingerprint,
PiPNotificationFingerprint, PiPNotificationFingerprint,
PreferenceScreenFingerprint,
TooltipContentFullscreenFingerprint, TooltipContentFullscreenFingerprint,
TooltipContentViewFingerprint TooltipContentViewFingerprint
) )
) { ) {
private const val INTEGRATIONS_SETTINGS_MENU_DESCRIPTOR =
"$GENERAL_PATH/SettingsMenuPatch;"
private const val CUSTOM_FILTER_CLASS_DESCRIPTOR = private const val CUSTOM_FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CustomFilter;" "$COMPONENTS_PATH/CustomFilter;"
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR = private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
@ -193,6 +199,29 @@ object LayoutComponentsPatch : BaseBytecodePatch(
// endregion // endregion
// region patch for hide setting menus
PreferenceScreenFingerprint.resultOrThrow().mutableMethod.apply {
val targetIndex =
PreferenceScreenFingerprint.indexOfPreferenceScreenInstruction(this)
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
val insertIndex = implementation!!.instructions.lastIndex
addInstructions(
insertIndex + 1, """
invoke-virtual {v$targetRegister}, $targetReference
move-result-object v$targetRegister
invoke-static {v$targetRegister}, $INTEGRATIONS_SETTINGS_MENU_DESCRIPTOR->hideSettingsMenu(Landroidx/preference/PreferenceScreen;)V
return-void
"""
)
removeInstruction(insertIndex)
}
// endregion
// region patch for hide snack bar // region patch for hide snack bar
BottomUiContainerFingerprint.resultOrThrow().let { BottomUiContainerFingerprint.resultOrThrow().let {

View File

@ -4,5 +4,5 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Compa
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object AccountListParentFingerprint : LiteralValueFingerprint( internal object AccountListParentFingerprint : LiteralValueFingerprint(
literalSupplier = { CompactListItem } literalSupplier = { CompactListItem },
) )

View File

@ -11,5 +11,5 @@ internal object AccountMenuParentFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT Opcode.MOVE_RESULT_OBJECT
), ),
literalSupplier = { CompactLink } literalSupplier = { CompactLink },
) )

View File

@ -6,5 +6,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint( internal object AccountSwitcherAccessibilityLabelFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
parameters = listOf("L", "Ljava/lang/Object;"), parameters = listOf("L", "Ljava/lang/Object;"),
literalSupplier = { AccountSwitcherAccessibility } literalSupplier = { AccountSwitcherAccessibility },
) )

View File

@ -15,5 +15,5 @@ internal object FloatingMicrophoneFingerprint : LiteralValueFingerprint(
Opcode.IF_EQZ, Opcode.IF_EQZ,
Opcode.RETURN_VOID Opcode.RETURN_VOID
), ),
literalSupplier = { Fab } literalSupplier = { Fab },
) )

View File

@ -9,5 +9,5 @@ internal object PiPNotificationFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"), parameters = listOf("L"),
literalSupplier = { EditSettingsAction } literalSupplier = { EditSettingsAction },
) )

View File

@ -0,0 +1,30 @@
package app.revanced.patches.youtube.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.general.components.fingerprints.PreferenceScreenFingerprint.indexOfPreferenceScreenInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionReversed
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object PreferenceScreenFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf(":android:show_fragment_args"),
customFingerprint = { methodDef, classDef ->
AccessFlags.SYNTHETIC.isSet(classDef.accessFlags) &&
indexOfPreferenceScreenInstruction(methodDef) >= 0
}
) {
fun indexOfPreferenceScreenInstruction(methodDef: Method) =
methodDef.indexOfFirstInstructionReversed {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL &&
reference?.returnType == "Landroidx/preference/PreferenceScreen;" &&
reference.parameterTypes.size == 0
}
}

View File

@ -4,5 +4,5 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object TooltipContentFullscreenFingerprint : LiteralValueFingerprint( internal object TooltipContentFullscreenFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
literalSupplier = { 45384061 } literalSupplier = { 45384061 },
) )

View File

@ -9,5 +9,5 @@ internal object TooltipContentViewFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"), parameters = listOf("L"),
literalSupplier = { ToolTipContentView } literalSupplier = { ToolTipContentView },
) )

View File

@ -6,7 +6,7 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal object AccessibilityOfflineButtonSyncFingerprint : LiteralValueFingerprint( internal object AccessibilityOfflineButtonSyncFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V", returnType = "V",
literalSupplier = { AccessibilityOfflineButtonSync } accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { AccessibilityOfflineButtonSync },
) )

View File

@ -2,19 +2,22 @@ package app.revanced.patches.youtube.general.layoutswitch
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint
import app.revanced.patches.youtube.general.layoutswitch.fingerprints.GetFormFactorFingerprint import app.revanced.patches.youtube.general.layoutswitch.fingerprints.FormFactorEnumConstructorFingerprint
import app.revanced.patches.youtube.general.layoutswitch.fingerprints.LayoutSwitchFingerprint import app.revanced.patches.youtube.general.layoutswitch.fingerprints.LayoutSwitchFingerprint
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH
import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Suppress("unused") @Suppress("unused")
object LayoutSwitchPatch : BaseBytecodePatch( object LayoutSwitchPatch : BaseBytecodePatch(
@ -23,52 +26,51 @@ object LayoutSwitchPatch : BaseBytecodePatch(
dependencies = setOf(SettingsPatch::class), dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE, compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf( fingerprints = setOf(
GetFormFactorFingerprint, CreatePlayerRequestBodyWithModelFingerprint,
FormFactorEnumConstructorFingerprint,
LayoutSwitchFingerprint LayoutSwitchFingerprint
) )
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$GENERAL_PATH/LayoutSwitchPatch;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// region patch for enable tablet layout val formFactorEnumClass = FormFactorEnumConstructorFingerprint
.resultOrThrow()
.mutableMethod
.definingClass
GetFormFactorFingerprint.resultOrThrow().let { CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.apply {
it.mutableMethod.apply { val index = indexOfFirstInstructionOrThrow {
val jumpIndex = indexOfFirstInstructionReversedOrThrow(Opcode.SGET_OBJECT) val reference = getReference<FieldReference>()
opcode == Opcode.IGET &&
addInstructionsWithLabels( reference?.definingClass == formFactorEnumClass &&
0, """ reference.type == "I"
invoke-static { }, $GENERAL_CLASS_DESCRIPTOR->enableTabletLayout()Z
move-result v0 # Free register
if-nez v0, :is_large_form_factor
""",
ExternalLabel(
"is_large_form_factor",
getInstruction(jumpIndex)
)
)
} }
val register = getInstruction<TwoRegisterInstruction>(index).registerA
addInstructions(
index + 1, """
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->getFormFactor(I)I
move-result v$register
"""
)
} }
// endregion
// region patch for enable phone layout
LayoutSwitchFingerprint.resultOrThrow().let { LayoutSwitchFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_NEZ) val index = indexOfFirstInstructionReversedOrThrow(Opcode.IF_NEZ)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions( addInstructions(
insertIndex, """ index, """
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->enablePhoneLayout(I)I invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->getWidthDp(I)I
move-result v$insertRegister move-result v$register
""" """
) )
} }
} }
// endregion
/** /**
* Add settings * Add settings
*/ */

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