From eb181dcf901bd9a730de4bb46cdd0ba27cc24838 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Mon, 10 Feb 2025 16:40:03 +0900 Subject: [PATCH] fix(YouTube Music - Hide ads): New type of `Premium promotion popups` are shown --- .../patches/ads/PremiumPromotionPatch.java | 66 ++++++++++++------- .../patches/music/ads/general/AdsPatch.kt | 26 +++++++- .../patches/music/ads/general/Fingerprints.kt | 28 ++++++++ .../utils/playservice/VersionCheckPatch.kt | 3 + .../utils/resourceid/SharedResourceIdPatch.kt | 6 ++ 5 files changed, 105 insertions(+), 24 deletions(-) diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/patches/ads/PremiumPromotionPatch.java b/extensions/shared/src/main/java/app/revanced/extension/music/patches/ads/PremiumPromotionPatch.java index 7a863606f..e8dd2be41 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/patches/ads/PremiumPromotionPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/patches/ads/PremiumPromotionPatch.java @@ -1,40 +1,60 @@ package app.revanced.extension.music.patches.ads; +import static app.revanced.extension.music.patches.general.GeneralPatch.disableDimBehind; +import static app.revanced.extension.shared.utils.StringRef.str; + +import android.app.Dialog; +import android.content.DialogInterface; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import app.revanced.extension.music.settings.Settings; +import app.revanced.extension.shared.settings.BaseSettings; import app.revanced.extension.shared.utils.Logger; +import app.revanced.extension.shared.utils.Utils; @SuppressWarnings("unused") public class PremiumPromotionPatch { + private static final boolean HIDE_PREMIUM_PROMOTION = + Settings.HIDE_PREMIUM_PROMOTION.get(); - public static void hidePremiumPromotion(View view) { - if (!Settings.HIDE_PREMIUM_PROMOTION.get()) - return; + public static void hidePremiumPromotionBottomSheet(View view) { + if (HIDE_PREMIUM_PROMOTION) { + view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { + try { + if (!(view instanceof ViewGroup viewGroup)) { + return; + } + if (!(viewGroup.getChildAt(0) instanceof ViewGroup mealBarLayoutRoot)) { + return; + } + if (!(mealBarLayoutRoot.getChildAt(0) instanceof LinearLayout linearLayout)) { + return; + } + if (!(linearLayout.getChildAt(0) instanceof ImageView imageView)) { + return; + } + if (imageView.getVisibility() == View.VISIBLE) { + view.setVisibility(View.GONE); + } + } catch (Exception ex) { + Logger.printException(() -> "hidePremiumPromotionBottomSheet failure", ex); + } + }); + } + } - view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { - try { - if (!(view instanceof ViewGroup viewGroup)) { - return; - } - if (!(viewGroup.getChildAt(0) instanceof ViewGroup mealBarLayoutRoot)) { - return; - } - if (!(mealBarLayoutRoot.getChildAt(0) instanceof LinearLayout linearLayout)) { - return; - } - if (!(linearLayout.getChildAt(0) instanceof ImageView imageView)) { - return; - } - if (imageView.getVisibility() == View.VISIBLE) { - view.setVisibility(View.GONE); - } - } catch (Exception ex) { - Logger.printException(() -> "hideGetPremium failure", ex); + public static void hidePremiumPromotionDialog(Dialog dialog, View contentView) { + if (HIDE_PREMIUM_PROMOTION) { + disableDimBehind(dialog.getWindow()); + dialog.setOnShowListener(DialogInterface::dismiss); + if (BaseSettings.ENABLE_DEBUG_LOGGING.get()) { + Utils.showToastShort(str("revanced_hide_premium_promotion_closed_toast")); } - }); + } else { + dialog.setContentView(contentView); + } } } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt index dbb54545f..9ae14aea4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt @@ -2,6 +2,7 @@ package app.revanced.patches.music.ads.general import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.music.navigation.components.navigationBarComponentsPatch import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE @@ -9,6 +10,8 @@ import app.revanced.patches.music.utils.extension.Constants.ADS_PATH import app.revanced.patches.music.utils.extension.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.navigation.navigationBarHookPatch import app.revanced.patches.music.utils.patch.PatchList.HIDE_ADS +import app.revanced.patches.music.utils.playservice.is_7_28_or_greater +import app.revanced.patches.music.utils.playservice.versionCheckPatch import app.revanced.patches.music.utils.resourceid.buttonContainer import app.revanced.patches.music.utils.resourceid.floatingLayout import app.revanced.patches.music.utils.resourceid.interstitialsContainer @@ -30,6 +33,7 @@ import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -58,6 +62,7 @@ val adsPatch = bytecodePatch( navigationBarComponentsPatch, // for 'Hide upgrade button' setting navigationBarHookPatch, sharedResourceIdPatch, + versionCheckPatch, ) execute { @@ -78,16 +83,35 @@ val adsPatch = bytecodePatch( // region patch for hide premium promotion popup + // get premium bottom sheet floatingLayoutFingerprint.methodOrThrow().apply { val targetIndex = indexOfFirstLiteralInstructionOrThrow(floatingLayout) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( targetIndex + 1, - "invoke-static {v$targetRegister}, $PREMIUM_PROMOTION_POP_UP_CLASS_DESCRIPTOR->hidePremiumPromotion(Landroid/view/View;)V" + "invoke-static {v$targetRegister}, $PREMIUM_PROMOTION_POP_UP_CLASS_DESCRIPTOR->hidePremiumPromotionBottomSheet(Landroid/view/View;)V" ) } + // get premium dialog in player + if (is_7_28_or_greater) { + getPremiumDialogFingerprint + .methodOrThrow(getPremiumDialogParentFingerprint) + .apply { + val setContentViewIndex = indexOfSetContentViewInstruction(this) + val dialogInstruction = getInstruction(setContentViewIndex) + val dialogRegister = dialogInstruction.registerC + val viewRegister = dialogInstruction.registerD + + replaceInstruction( + setContentViewIndex, + "invoke-static {v$dialogRegister, v$viewRegister}, " + + " $PREMIUM_PROMOTION_POP_UP_CLASS_DESCRIPTOR->hidePremiumPromotionDialog(Landroid/app/Dialog;Landroid/view/View;)V" + ) + } + } + // endregion // region patch for hide premium renewal banner diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ads/general/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/ads/general/Fingerprints.kt index 1c06ae47d..a70e8e57a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ads/general/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ads/general/Fingerprints.kt @@ -3,13 +3,18 @@ package app.revanced.patches.music.ads.general import app.revanced.patches.music.utils.resourceid.buttonContainer import app.revanced.patches.music.utils.resourceid.floatingLayout import app.revanced.patches.music.utils.resourceid.interstitialsContainer +import app.revanced.patches.music.utils.resourceid.modernDialogBackground import app.revanced.patches.music.utils.resourceid.musicNotifierShelf import app.revanced.patches.music.utils.resourceid.privacyTosFooter import app.revanced.patches.music.utils.resourceid.slidingDialogAnimation import app.revanced.util.fingerprint.legacyFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import app.revanced.util.or 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 val accountMenuFooterFingerprint = legacyFingerprint( name = "accountMenuFooterFingerprint", @@ -34,6 +39,29 @@ internal val floatingLayoutFingerprint = legacyFingerprint( literals = listOf(floatingLayout) ) +internal val getPremiumDialogParentFingerprint = legacyFingerprint( + name = "getPremiumDialogParentFingerprint", + returnType = "Landroid/graphics/drawable/Drawable;", + accessFlags = AccessFlags.PROTECTED.value, + parameters = listOf("Landroid/content/Context;"), + literals = listOf(modernDialogBackground) +) + +internal val getPremiumDialogFingerprint = legacyFingerprint( + name = "getPremiumDialogFingerprint", + returnType = "Landroid/app/Dialog;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("Landroid/os/Bundle;"), + customFingerprint = { method, _ -> + indexOfSetContentViewInstruction(method) >= 0 + } +) + +internal fun indexOfSetContentViewInstruction(method: Method) = + method.indexOfFirstInstruction { + getReference()?.toString() == "Landroid/app/Dialog;->setContentView(Landroid/view/View;)V" + } + internal val getPremiumTextViewFingerprint = legacyFingerprint( name = "getPremiumTextViewFingerprint", returnType = "V", diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/playservice/VersionCheckPatch.kt index abe386ff8..cdadd5a4c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/utils/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/playservice/VersionCheckPatch.kt @@ -31,6 +31,8 @@ var is_7_25_or_greater = false private set var is_7_27_or_greater = false private set +var is_7_28_or_greater = false + private set var is_7_29_or_greater = false private set var is_7_33_or_greater = false @@ -65,6 +67,7 @@ val versionCheckPatch = resourcePatch( is_7_23_or_greater = 244199000 <= playStoreServicesVersion is_7_25_or_greater = 244399000 <= playStoreServicesVersion is_7_27_or_greater = 244515000 <= playStoreServicesVersion + is_7_28_or_greater = 244699000 <= playStoreServicesVersion is_7_29_or_greater = 244799000 <= playStoreServicesVersion is_7_33_or_greater = 245199000 <= playStoreServicesVersion is_8_03_or_greater = 250399000 <= playStoreServicesVersion diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt index 3363e56b0..d0c1c9cc4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt @@ -61,6 +61,8 @@ var miniPlayerPlayPauseReplayButton = -1L private set var miniPlayerViewPager = -1L private set +var modernDialogBackground = -1L + private set var musicNotifierShelf = -1L private set var musicTasteBuilderShelf = -1L @@ -208,6 +210,10 @@ internal val sharedResourceIdPatch = resourcePatch( ID, "mini_player_view_pager" ] + modernDialogBackground = resourceMappings[ + DRAWABLE, + "modern_dialog_background" + ] musicNotifierShelf = resourceMappings[ LAYOUT, "music_notifier_shelf"