diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java index 36d7f8d97c..03f4e0187d 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java @@ -148,12 +148,12 @@ public static String getApplicationName() { /** * Hide a view by setting its layout height and width to 1dp. * - * @param condition The setting to check for hiding the view. + * @param setting The setting to check for hiding the view. * @param view The view to hide. */ - public static void hideViewBy0dpUnderCondition(BooleanSetting condition, View view) { - if (hideViewBy0dpUnderCondition(condition.get(), view)) { - Logger.printDebug(() -> "View hidden by setting: " + condition); + public static void hideViewBy0dpUnderCondition(BooleanSetting setting, View view) { + if (hideViewBy0dpUnderCondition(setting.get(), view)) { + Logger.printDebug(() -> "View hidden by setting: " + setting); } } @@ -165,22 +165,47 @@ public static void hideViewBy0dpUnderCondition(BooleanSetting condition, View vi */ public static boolean hideViewBy0dpUnderCondition(boolean condition, View view) { if (condition) { - hideViewByLayoutParams(view); + hideViewBy0dp(view); return true; } return false; } + /** + * Hide a view by setting its layout params to 0x0 + * @param view The view to hide. + */ + public static void hideViewBy0dp(View view) { + if (view instanceof LinearLayout) { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 0); + view.setLayoutParams(layoutParams); + } else if (view instanceof FrameLayout) { + FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(0, 0); + view.setLayoutParams(layoutParams2); + } else if (view instanceof RelativeLayout) { + RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(0, 0); + view.setLayoutParams(layoutParams3); + } else if (view instanceof Toolbar) { + Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(0, 0); + view.setLayoutParams(layoutParams4); + } else { + ViewGroup.LayoutParams params = view.getLayoutParams(); + params.width = 0; + params.height = 0; + view.setLayoutParams(params); + } + } + /** * Hide a view by setting its visibility to GONE. * - * @param condition The setting to check for hiding the view. + * @param setting The setting to check for hiding the view. * @param view The view to hide. */ - public static void hideViewUnderCondition(BooleanSetting condition, View view) { - if (hideViewUnderCondition(condition.get(), view)) { - Logger.printDebug(() -> "View hidden by setting: " + condition); + public static void hideViewUnderCondition(BooleanSetting setting, View view) { + if (hideViewUnderCondition(setting.get(), view)) { + Logger.printDebug(() -> "View hidden by setting: " + setting); } } @@ -199,14 +224,14 @@ public static boolean hideViewUnderCondition(boolean condition, View view) { return false; } - public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting condition, View view) { - if (hideViewByRemovingFromParentUnderCondition(condition.get(), view)) { - Logger.printDebug(() -> "View hidden by setting: " + condition); + public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting setting, View view) { + if (hideViewByRemovingFromParentUnderCondition(setting.get(), view)) { + Logger.printDebug(() -> "View hidden by setting: " + setting); } } - public static boolean hideViewByRemovingFromParentUnderCondition(boolean setting, View view) { - if (setting) { + public static boolean hideViewByRemovingFromParentUnderCondition(boolean condition, View view) { + if (condition) { ViewParent parent = view.getParent(); if (parent instanceof ViewGroup parentGroup) { parentGroup.removeView(view); @@ -714,34 +739,6 @@ public static NetworkType getNetworkType() { || (type == ConnectivityManager.TYPE_BLUETOOTH) ? NetworkType.MOBILE : NetworkType.OTHER; } - /** - * Hide a view by setting its layout params to 0x0 - * @param view The view to hide. - */ - public static void hideViewByLayoutParams(View view) { - if (view instanceof LinearLayout) { - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 0); - view.setLayoutParams(layoutParams); - } else if (view instanceof FrameLayout) { - FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(0, 0); - view.setLayoutParams(layoutParams2); - } else if (view instanceof RelativeLayout) { - RelativeLayout.LayoutParams layoutParams3 = new RelativeLayout.LayoutParams(0, 0); - view.setLayoutParams(layoutParams3); - } else if (view instanceof Toolbar) { - Toolbar.LayoutParams layoutParams4 = new Toolbar.LayoutParams(0, 0); - view.setLayoutParams(layoutParams4); - } else if (view instanceof ViewGroup) { - ViewGroup.LayoutParams layoutParams5 = new ViewGroup.LayoutParams(0, 0); - view.setLayoutParams(layoutParams5); - } else { - ViewGroup.LayoutParams params = view.getLayoutParams(); - params.width = 0; - params.height = 0; - view.setLayoutParams(params); - } - } - /** * Creates a custom dialog with a styled layout, including a title, message, buttons, and an * optional EditText. The dialog's appearance adapts to the app's dark mode setting, with diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DownloadsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DownloadsPatch.java index 6da31b6a4c..bbe01ec89f 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DownloadsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DownloadsPatch.java @@ -23,7 +23,7 @@ public final class DownloadsPatch { /** * Injection point. */ - public static void activityCreated(Activity mainActivity) { + public static void setMainActivity(Activity mainActivity) { activityRef = new WeakReference<>(mainActivity); } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java index 7021cc6f9f..e5ec52b771 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java @@ -62,6 +62,13 @@ public static void hideNavigationButtonLabels(TextView navigationLabelsView) { hideViewUnderCondition(Settings.HIDE_NAVIGATION_BUTTON_LABELS, navigationLabelsView); } + /** + * Injection point. + */ + public static boolean useAnimatedNavigationButtons(boolean original) { + return Settings.NAVIGATION_BAR_ANIMATIONS.get(); + } + /** * Injection point. */ diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java index e0a1e3c700..02fc01c9fa 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java @@ -20,15 +20,6 @@ public enum ShortsPlayerType { REGULAR_PLAYER_FULLSCREEN } - static { - if (!VersionCheckPatch.IS_19_46_OR_GREATER - && Settings.SHORTS_PLAYER_TYPE.get() == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN) { - // User imported newer settings to an older app target. - Logger.printInfo(() -> "Resetting " + Settings.SHORTS_PLAYER_TYPE); - Settings.SHORTS_PLAYER_TYPE.resetToDefault(); - } - } - private static WeakReference mainActivityRef = new WeakReference<>(null); private static volatile boolean overrideBackPressToExit; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java index ff2d778741..9a7989d9a1 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java @@ -24,18 +24,20 @@ private static boolean isFullScreenPatchIncluded() { /** * Injection point. + * + * Returns negated value. */ - public static boolean openVideoFullscreenPortrait(boolean original) { + public static boolean doNotOpenVideoFullscreenPortrait(boolean original) { Boolean openFullscreen = openNextVideoFullscreen; if (openFullscreen != null) { openNextVideoFullscreen = null; - return openFullscreen; + return !openFullscreen; } if (!isFullScreenPatchIncluded()) { return original; } - return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get(); + return !Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get(); } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/PlayerControlsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/PlayerControlsPatch.java index a8458310da..be7fe91190 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/PlayerControlsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/PlayerControlsPatch.java @@ -42,7 +42,7 @@ public void onGlobalLayout() { Logger.printDebug(() -> "fullscreen button visibility: " + (visibility == View.VISIBLE ? "VISIBLE" : - visibility == View.GONE ? "GONE" : "INVISIBLE")); + visibility == View.GONE ? "GONE" : "INVISIBLE")); fullscreenButtonVisibilityChanged(visibility == View.VISIBLE); } @@ -57,11 +57,4 @@ public void onGlobalLayout() { private static void fullscreenButtonVisibilityChanged(boolean isVisible) { // Code added during patching. } - - /** - * Injection point. - */ - public static String getPlayerTopControlsLayoutResourceName(String original) { - return "default"; - } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ShortsAutoplayPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ShortsAutoplayPatch.java index 9e5aff20b1..e7de421368 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ShortsAutoplayPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ShortsAutoplayPatch.java @@ -2,8 +2,6 @@ import android.app.Activity; -import androidx.annotation.Nullable; - import java.lang.ref.WeakReference; import java.util.Objects; @@ -78,7 +76,7 @@ public static void setYTShortsRepeatEnum(Enum ytEnum) { /** * Injection point. */ - public static Enum changeShortsRepeatBehavior(@Nullable Enum original) { + public static Enum changeShortsRepeatBehavior(Enum original) { try { final boolean autoplay; @@ -95,19 +93,19 @@ public static Enum changeShortsRepeatBehavior(@Nullable Enum original) { autoplay = Settings.SHORTS_AUTOPLAY.get(); } - final ShortsLoopBehavior behavior = autoplay + Enum overrideBehavior = (autoplay ? ShortsLoopBehavior.SINGLE_PLAY - : ShortsLoopBehavior.REPEAT; + : ShortsLoopBehavior.REPEAT).ytEnumValue; - if (behavior.ytEnumValue != null) { + if (overrideBehavior != null) { Logger.printDebug(() -> { String name = (original == null ? "unknown (null)" : original.name()); - return behavior == original + return overrideBehavior == original ? "Behavior setting is same as original. Using original: " + name - : "Changing Shorts repeat behavior from: " + name + " to: " + behavior.name(); + : "Changing Shorts repeat behavior from: " + name + " to: " + overrideBehavior.name(); }); - return behavior.ytEnumValue; + return overrideBehavior; } if (original == null) { @@ -118,13 +116,12 @@ public static Enum changeShortsRepeatBehavior(@Nullable Enum original) { return unknown; } } catch (Exception ex) { - Logger.printException(() -> "changeShortsRepeatBehavior failure", ex); + Logger.printException(() -> "changeShortsRepeatState failure", ex); } return original; } - /** * Injection point. */ diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VersionCheckPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VersionCheckPatch.java index 2844b53db7..3ae92d77ab 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VersionCheckPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VersionCheckPatch.java @@ -19,5 +19,6 @@ private static boolean isVersionOrGreater(String version) { public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00"); @Deprecated public static final boolean IS_19_34_OR_GREATER = isVersionOrGreater("19.34.00"); - public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00"); + + public static final boolean IS_20_21_OR_GREATER = isVersionOrGreater("20.21.00"); } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java index 347491a46e..392ebcdbe6 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LayoutComponentsFilter.java @@ -1,5 +1,6 @@ package app.revanced.extension.youtube.patches.components; +import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_20_21_OR_GREATER; import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton; import android.graphics.drawable.Drawable; @@ -399,11 +400,23 @@ public static int hideInSearch(int height) { : height; } + private static final boolean HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED + = Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS.get(); + /** * Injection point. */ public static void hideInRelatedVideos(View chipView) { - Utils.hideViewBy0dpUnderCondition(Settings.HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS, chipView); + // Cannot use 0dp hide with later targets, otherwise the suggested videos + // can be shown in full screen mode. + // This behavior may also be present in earlier app targets. + if (IS_20_21_OR_GREATER) { + // FIXME: The filter bar is still briefly shown when dragging the suggested videos + // below the video player. + Utils.hideViewUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView); + } else { + Utils.hideViewBy0dpUnderCondition(HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS_ENABLED, chipView); + } } private static final boolean HIDE_DOODLES_ENABLED = Settings.HIDE_DOODLES.get(); @@ -430,7 +443,7 @@ public static void hideShowMoreButton(View view) { && NavigationBar.isSearchBarActive() // Search bar can be active but behind the player. && !PlayerType.getCurrent().isMaximizedOrFullscreen()) { - Utils.hideViewByLayoutParams(view); + Utils.hideViewBy0dp(view); } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java index 09117f0404..ad184b465e 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/LithoFilterPatch.java @@ -48,7 +48,7 @@ public String toString() { /** * Search through a byte array for all ASCII strings. */ - private static void findAsciiStrings(StringBuilder builder, byte[] buffer) { + static void findAsciiStrings(StringBuilder builder, byte[] buffer) { // Valid ASCII values (ignore control characters). final int minimumAscii = 32; // 32 = space character final int maximumAscii = 126; // 127 = delete character @@ -96,7 +96,7 @@ private static void findAsciiStrings(StringBuilder builder, byte[] buffer) { private static final class DummyFilter extends Filter { } private static final Filter[] filters = new Filter[] { - new DummyFilter() // Replaced by patch. + new DummyFilter() // Replaced patching, do not touch. }; private static final StringTrieSearch pathSearchTree = new StringTrieSearch(); @@ -108,11 +108,7 @@ private static final class DummyFilter extends Filter { } * Because litho filtering is multi-threaded and the buffer is passed in from a different injection point, * the buffer is saved to a ThreadLocal so each calling thread does not interfere with other threads. */ - private static final ThreadLocal bufferThreadLocal = new ThreadLocal<>(); - /** - * Results of calling {@link #filter(String, StringBuilder)}. - */ - private static final ThreadLocal filterResult = new ThreadLocal<>(); + private static final ThreadLocal bufferThreadLocal = new ThreadLocal<>(); static { for (Filter filter : filters) { @@ -167,58 +163,52 @@ private static void filterUsingCallbacks(StringTrieSearch pathSearchTree, /** * Injection point. Called off the main thread. + * Targets 20.22+ */ - @SuppressWarnings("unused") - public static void setProtoBuffer(@Nullable ByteBuffer protobufBuffer) { + public static void setProtoBuffer(byte[] buffer) { // Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes. // This is intentional, as it appears the buffer can be set once and then filtered multiple times. // The buffer will be cleared from memory after a new buffer is set by the same thread, // or when the calling thread eventually dies. - if (protobufBuffer == null) { + bufferThreadLocal.set(buffer); + } + + /** + * Injection point. Called off the main thread. + * Targets 20.21 and lower. + */ + public static void setProtoBuffer(@Nullable ByteBuffer buffer) { + // Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes. + // This is intentional, as it appears the buffer can be set once and then filtered multiple times. + // The buffer will be cleared from memory after a new buffer is set by the same thread, + // or when the calling thread eventually dies. + if (buffer == null || !buffer.hasArray()) { // It appears the buffer can be cleared out just before the call to #filter() // Ignore this null value and retain the last buffer that was set. - Logger.printDebug(() -> "Ignoring null protobuffer"); + Logger.printDebug(() -> "Ignoring null or empty buffer: " + buffer); } else { - bufferThreadLocal.set(protobufBuffer); + setProtoBuffer(buffer.array()); } } /** * Injection point. */ - public static boolean shouldFilter() { - Boolean shouldFilter = filterResult.get(); - return shouldFilter != null && shouldFilter; - } - - /** - * Injection point. Called off the main thread, and commonly called by multiple threads at the same time. - */ - public static void filter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) { - filterResult.set(handleFiltering(lithoIdentifier, pathBuilder)); - } - - private static boolean handleFiltering(@Nullable String lithoIdentifier, StringBuilder pathBuilder) { + public static boolean shouldFilter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) { try { if (pathBuilder.length() == 0) { return false; } - ByteBuffer protobufBuffer = bufferThreadLocal.get(); - final byte[] bufferArray; + byte[] buffer = bufferThreadLocal.get(); // Potentially the buffer may have been null or never set up until now. // Use an empty buffer so the litho id/path filters still work correctly. - if (protobufBuffer == null) { - bufferArray = EMPTY_BYTE_ARRAY; - } else if (!protobufBuffer.hasArray()) { - Logger.printDebug(() -> "Proto buffer does not have an array, using an empty buffer array"); - bufferArray = EMPTY_BYTE_ARRAY; - } else { - bufferArray = protobufBuffer.array(); + if (buffer == null) { + buffer = EMPTY_BYTE_ARRAY; } - LithoFilterParameters parameter = new LithoFilterParameters(lithoIdentifier, - pathBuilder.toString(), bufferArray); + LithoFilterParameters parameter = new LithoFilterParameters( + lithoIdentifier, pathBuilder.toString(), buffer); Logger.printDebug(() -> "Searching " + parameter); if (parameter.identifier != null && identifierSearchTree.matches(parameter.identifier, parameter)) { diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java index b334354c6e..0f89ccbc89 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java @@ -396,17 +396,6 @@ private static boolean shouldHideShortsFeedItems() { }; } - /** - * Injection point. Only used if patching older than 19.03. - * This hook may be obsolete even for old versions - * as they now use a litho layout like newer versions. - */ - public static void hideShortsShelf(final View shortsShelfView) { - if (shouldHideShortsFeedItems()) { - Utils.hideViewByLayoutParams(shortsShelfView); - } - } - public static int getSoundButtonSize(int original) { if (Settings.HIDE_SHORTS_SOUND_BUTTON.get()) { return 0; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java index ade422260b..6b96812957 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java @@ -258,7 +258,8 @@ private static SpannableString createDislikeSpan(@NonNull Spanned oldSpannable, // middle separator String middleSeparatorString = compactLayout ? " " + MIDDLE_SEPARATOR_CHARACTER + " " - : " \u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009 "; // u2009 = 'narrow space' character + : " \u2009\u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009\u2009 "; // u2009 = 'narrow space' + final int shapeInsertionIndex = middleSeparatorString.length() / 2; Spannable middleSeparatorSpan = new SpannableString(middleSeparatorString); ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape()); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index 83fc2a032e..438dbcb305 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -11,6 +11,7 @@ import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage; import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode; import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability; +import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL; @@ -43,7 +44,6 @@ import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability; import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption; import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime; -import app.revanced.extension.youtube.patches.MiniplayerPatch; import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings; import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider.SwipeOverlayStyle; @@ -168,8 +168,8 @@ public class Settings extends BaseSettings { public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability()); - public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability()); - public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3)); + public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerHideOverlayButtonsAvailability()); + public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3, MODERN_4)); public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, MINIPLAYER_TYPE.availability(MODERN_1)); public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, MINIPLAYER_ANY_MODERN); public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, MINIPLAYER_ANY_MODERN); @@ -253,6 +253,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_hide_notifications_button", FALSE, true); public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true, "revanced_switch_create_with_notifications_button_user_dialog_message"); + public static final BooleanSetting NAVIGATION_BAR_ANIMATIONS = new BooleanSetting("revanced_navigation_bar_animations", FALSE); public static final BooleanSetting DISABLE_TRANSLUCENT_STATUS_BAR = new BooleanSetting("revanced_disable_translucent_status_bar", FALSE, true, "revanced_disable_translucent_status_bar_user_dialog_message"); public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT = new BooleanSetting("revanced_disable_translucent_navigation_bar_light", FALSE, true); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/shared/PlayerType.kt b/extensions/youtube/src/main/java/app/revanced/extension/youtube/shared/PlayerType.kt index 147abc13f0..0b97b05c6e 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/shared/PlayerType.kt +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/shared/PlayerType.kt @@ -2,7 +2,6 @@ package app.revanced.extension.youtube.shared import app.revanced.extension.shared.Logger import app.revanced.extension.youtube.Event -import app.revanced.extension.youtube.patches.VideoInformation /** * Regular player type. diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java index 22259d5714..55d9c02115 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java @@ -9,7 +9,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import java.lang.reflect.Field; import java.util.*; import app.revanced.extension.shared.Logger; @@ -99,9 +98,9 @@ public class SegmentPlaybackController { @Nullable private static String timeWithoutSegments; - private static int sponsorBarAbsoluteLeft; - private static int sponsorAbsoluteBarRight; - private static int sponsorBarThickness; + private static int seekbarAbsoluteLeft; + private static int seekbarAbsoluteRight; + private static int seekbarThickness; @Nullable static SponsorSegment[] getSegments() { @@ -628,31 +627,17 @@ public static void onSkipSegmentClicked(@NonNull SponsorSegment segment) { * Injection point */ @SuppressWarnings("unused") - public static void setSponsorBarRect(final Object self) { - try { - Field field = self.getClass().getDeclaredField("replaceMeWithsetSponsorBarRect"); - field.setAccessible(true); - Rect rect = (Rect) Objects.requireNonNull(field.get(self)); - setSponsorBarAbsoluteLeft(rect); - setSponsorBarAbsoluteRight(rect); - } catch (Exception ex) { - Logger.printException(() -> "setSponsorBarRect failure", ex); - } - } - - private static void setSponsorBarAbsoluteLeft(Rect rect) { - final int left = rect.left; - if (sponsorBarAbsoluteLeft != left) { - Logger.printDebug(() -> "setSponsorBarAbsoluteLeft: " + left); - sponsorBarAbsoluteLeft = left; + public static void setSeekbarRectangle(Rect seekbarRect) { + final int left = seekbarRect.left; + if (seekbarAbsoluteLeft != left) { + Logger.printDebug(() -> "setSeekbarRectangle left: " + left); + seekbarAbsoluteLeft = left; } - } - private static void setSponsorBarAbsoluteRight(Rect rect) { - final int right = rect.right; - if (sponsorAbsoluteBarRight != right) { - Logger.printDebug(() -> "setSponsorBarAbsoluteRight: " + right); - sponsorAbsoluteBarRight = right; + final int right = seekbarRect.right; + if (seekbarAbsoluteRight != right) { + Logger.printDebug(() -> "setSeekbarRectangle right: " + right); + seekbarAbsoluteRight = right; } } @@ -660,8 +645,8 @@ private static void setSponsorBarAbsoluteRight(Rect rect) { * Injection point */ @SuppressWarnings("unused") - public static void setSponsorBarThickness(int thickness) { - sponsorBarThickness = thickness; + public static void setSeekbarThickness(int thickness) { + seekbarThickness = thickness; } /** @@ -736,17 +721,17 @@ private static void calculateTimeWithoutSegments() { * Injection point. */ @SuppressWarnings("unused") - public static void drawSponsorTimeBars(final Canvas canvas, final float posY) { + public static void drawSegmentTimeBars(final Canvas canvas, final float posY) { try { if (segments == null) return; final long videoLength = VideoInformation.getVideoLength(); if (videoLength <= 0) return; - final int thicknessDiv2 = sponsorBarThickness / 2; // rounds down - final float top = posY - (sponsorBarThickness - thicknessDiv2); + final int thicknessDiv2 = seekbarThickness / 2; // rounds down + final float top = posY - (seekbarThickness - thicknessDiv2); final float bottom = posY + thicknessDiv2; - final float videoMillisecondsToPixels = (1f / videoLength) * (sponsorAbsoluteBarRight - sponsorBarAbsoluteLeft); - final float leftPadding = sponsorBarAbsoluteLeft; + final float videoMillisecondsToPixels = (1f / videoLength) * (seekbarAbsoluteRight - seekbarAbsoluteLeft); + final float leftPadding = seekbarAbsoluteLeft; for (SponsorSegment segment : segments) { final float left = leftPadding + segment.start * videoMillisecondsToPixels; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8588ab0f67..d9604e2892 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,8 @@ [versions] -revanced-patcher = "21.0.0" +revanced-patcher = "22.0.0" # Tracking https://github.com/google/smali/issues/64. #noinspection GradleDependency -smali = "3.0.5" +smali = "3.0.8" # 8.3.0 causes java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818. #noinspection GradleDependency agp = "8.2.2" diff --git a/patches/api/patches.api b/patches/api/patches.api index 0c4935b4a6..21ca59710f 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -64,10 +64,6 @@ public final class app/revanced/patches/all/misc/debugging/EnableAndroidDebuggin public static final fun getEnableAndroidDebuggingPatch ()Lapp/revanced/patcher/patch/ResourcePatch; } -public final class app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatchKt { - public static final fun getChangeDataDirectoryLocationPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatchKt { public static final fun getExportInternalDataDocumentsProviderPatch ()Lapp/revanced/patcher/patch/ResourcePatch; } @@ -220,10 +216,6 @@ public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatc public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatchKt { - public static final fun getRestoreHiddenBackUpWhileChargingTogglePatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictionsKt { public static final fun getRemoveDeviceRestrictionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -288,14 +280,6 @@ public final class app/revanced/patches/messenger/inbox/HideInboxSubtabsPatchKt public static final fun getHideInboxSubtabsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatchKt { - public static final fun getDisableSwitchingEmojiToStickerPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - -public final class app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatchKt { - public static final fun getDisableTypingIndicatorPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/messenger/layout/HideFacebookButtonPatchKt { public static final fun getHideFacebookButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -308,10 +292,6 @@ public final class app/revanced/patches/messenger/misc/extension/ExtensionPatchK public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/messenger/navbar/RemoveMetaAITabPatchKt { - public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/meta/ads/HideAdsPatchKt { public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -336,10 +316,6 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman public static final fun getPermanentRepeatPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatchKt { - public static final fun getPermanentShufflePatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/music/layout/compactheader/HideCategoryBarKt { public static final fun getHideCategoryBar ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -404,10 +380,6 @@ public final class app/revanced/patches/nunl/firebase/SpoofCertificatePatchKt { public static final fun getSpoofCertificatePatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/nyx/misc/pro/UnlockProPatchKt { - public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatchKt { public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -603,16 +575,11 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/ public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatchKt { - public static final fun getFixVideoDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatchKt { public static final fun getDisableScreenshotPopupPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } public final class app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatchKt { - public static final fun getUnlockPremiumIconPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getUnlockPremiumIconsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -638,26 +605,22 @@ public final class app/revanced/patches/shared/misc/extension/ExtensionHook { public final class app/revanced/patches/shared/misc/extension/SharedExtensionPatchKt { public static final fun extensionHook (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lapp/revanced/patcher/Fingerprint;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook; - public static final fun extensionHook (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook; + public static final fun extensionHook (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0; public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lapp/revanced/patcher/Fingerprint;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook; - public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patches/shared/misc/extension/ExtensionHook; - public static final fun sharedExtensionPatch (Ljava/lang/String;[Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch; - public static final fun sharedExtensionPatch ([Lapp/revanced/patches/shared/misc/extension/ExtensionHook;)Lapp/revanced/patcher/patch/BytecodePatch; + public static synthetic fun extensionHook$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function0; + public static final fun sharedExtensionPatch (Ljava/lang/String;[Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch; + public static final fun sharedExtensionPatch ([Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch; } public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatchKt { public static final fun getVerticalScrollPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/shared/misc/gms/FingerprintsKt { - public static final field GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME Ljava/lang/String; -} - public final class app/revanced/patches/shared/misc/gms/GmsCoreSupportPatchKt { public static final fun gmsCoreSupportPatch (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch; public static synthetic fun gmsCoreSupportPatch$default (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch; - public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch; - public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; + public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch; + public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; } public final class app/revanced/patches/shared/misc/hex/HexPatchKt { @@ -674,6 +637,7 @@ public final class app/revanced/patches/shared/misc/hex/Replacement$Companion { } public final class app/revanced/patches/shared/misc/mapping/ResourceElement { + public fun (Ljava/lang/String;Ljava/lang/String;J)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; public final fun component3 ()J @@ -688,9 +652,12 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceElement { } public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatchKt { - public static final fun get (Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)J + public static final fun getResourceElements ()Ljava/util/Collection; + public static final fun getResourceId (Ljava/lang/String;Ljava/lang/String;)J public static final fun getResourceMappingPatch ()Lapp/revanced/patcher/patch/ResourcePatch; - public static final fun getResourceMappings ()Ljava/util/List; + public static final fun hasResourceId (Ljava/lang/String;Ljava/lang/String;)Z + public static final fun resourceLiteral (Ljava/lang/String;Ljava/lang/String;I)Lapp/revanced/patcher/LiteralFilter; + public static synthetic fun resourceLiteral$default (Ljava/lang/String;Ljava/lang/String;IILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; } public final class app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatchKt { @@ -700,7 +667,6 @@ public final class app/revanced/patches/shared/misc/pairip/license/DisableLicens public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt { public static final fun overrideThemeColors (Ljava/lang/String;Ljava/lang/String;)V public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch; - public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch; public static synthetic fun settingsPatch$default (Ljava/util/List;Ljava/util/Set;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; } @@ -793,8 +759,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/ListPref public fun ()V public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;)V public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/util/resource/ArrayResource;Lapp/revanced/util/resource/ArrayResource;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getEntries ()Lapp/revanced/util/resource/ArrayResource; public final fun getEntriesKey ()Ljava/lang/String; public final fun getEntryValues ()Lapp/revanced/util/resource/ArrayResource; @@ -902,10 +868,6 @@ public final class app/revanced/patches/spotify/layout/theme/CustomThemePatchKt public static final fun getCustomThemePatch ()Lapp/revanced/patcher/patch/ResourcePatch; } -public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt { - public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/spotify/misc/UnlockPremiumPatchKt { public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -918,10 +880,6 @@ public final class app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatchKt public static final fun getSpoofPackageInfoPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt { - public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatchKt { public static final fun getFixFacebookLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -938,10 +896,6 @@ public final class app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunch public static final fun getFixThirdPartyLaunchersWidgets ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt { - public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/stocard/layout/HideOffersTabPatchKt { public static final fun getHideOffersTabPatch ()Lapp/revanced/patcher/patch/ResourcePatch; } @@ -1158,10 +1112,6 @@ public final class app/revanced/patches/twitter/misc/links/SanitizeSharingLinksP public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt { - public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/warnwetter/misc/firebasegetcert/FirebaseGetCertPatchKt { public static final fun getFirebaseGetCertPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1170,10 +1120,6 @@ public final class app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnloc public static final fun getPromoCodeUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatchKt { - public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/ad/general/HideAdsPatchKt { public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1267,15 +1213,7 @@ public final class app/revanced/patches/youtube/layout/hide/fullscreenambientmod } public final class app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatchKt { - public static final fun getAlbumCardId ()J - public static final fun getBarContainerHeightId ()J - public static final fun getCrowdfundingBoxId ()J - public static final fun getExpandButtonDownId ()J - public static final fun getFabButtonId ()J - public static final fun getFilterBarHeightId ()J public static final fun getHideLayoutComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; - public static final fun getRelatedChipCloudMarginId ()J - public static final fun getYouTubeLogo ()J } public final class app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatchKt { @@ -1294,18 +1232,10 @@ public final class app/revanced/patches/youtube/layout/hide/rollingnumber/Disabl public static final fun getDisableRollingNumberAnimationPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatchKt { - public static final fun getHideSeekbarPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatchKt { public static final fun getHideShortsComponentsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatchKt { - public static final fun getDisableSuggestedVideoEndScreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/layout/hide/time/HideTimestampPatchKt { public static final fun getHideTimestampPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1318,14 +1248,6 @@ public final class app/revanced/patches/youtube/layout/panels/popup/PlayerPopupP public static final fun getPlayerPopupPanelsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatchKt { - public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch; -} - -public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt { - public static final fun getOpenVideosFullscreen ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatchKt { public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1380,10 +1302,6 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl public static final fun getDisableResumingShortsOnStartupPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt { - public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/layout/theme/LithoColorHookPatchKt { public static final fun getLithoColorHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getLithoColorOverrideHook ()Lkotlin/jvm/functions/Function2; @@ -1429,14 +1347,6 @@ public final class app/revanced/patches/youtube/misc/extension/SharedExtensionPa public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatchKt { - public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - -public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatchKt { - public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/misc/fix/playbackspeed/FIxPlaybackSpeedWhilePlayingPatchKt { public static final fun getFixPlaybackSpeedWhilePlayingPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1491,9 +1401,6 @@ public final class app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPa public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPatchKt { public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch; - public static final fun is_19_03_or_greater ()Z - public static final fun is_19_04_or_greater ()Z - public static final fun is_19_16_or_greater ()Z public static final fun is_19_17_or_greater ()Z public static final fun is_19_18_or_greater ()Z public static final fun is_19_23_or_greater ()Z @@ -1518,6 +1425,10 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat public static final fun is_20_10_or_greater ()Z public static final fun is_20_14_or_greater ()Z public static final fun is_20_15_or_greater ()Z + public static final fun is_20_19_or_greater ()Z + public static final fun is_20_20_or_greater ()Z + public static final fun is_20_21_or_greater ()Z + public static final fun is_20_22_or_greater ()Z } public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt { @@ -1560,10 +1471,6 @@ public final class app/revanced/patches/youtube/misc/spoof/UserAgentClientSpoofP public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatchKt { - public static final fun getZoomHapticsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatchKt { public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1624,14 +1531,6 @@ public final class app/revanced/patches/youtube/video/videoid/VideoIdPatchKt { public static final fun hookVideoId (Ljava/lang/String;)V } -public final class app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatchKt { - public static final fun getRestoreOldVideoQualityMenuPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - -public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatchKt { - public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch; -} - public final class app/revanced/util/BytecodeUtilsKt { public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/util/smali/ExternalLabel;)V diff --git a/patches/build.gradle.kts b/patches/build.gradle.kts index eecadbd25c..a04cb5b16f 100644 --- a/patches/build.gradle.kts +++ b/patches/build.gradle.kts @@ -12,6 +12,12 @@ patches { } } +repositories { + mavenLocal() + gradlePluginPortal() + google() +} + dependencies { // Required due to smali, or build fails. Can be removed once smali is bumped. implementation(libs.guava) diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatch.kt deleted file mode 100644 index 8046c11fc3..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/ChangeDataDirectoryLocationPatch.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.all.misc.directory - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.all.misc.directory.documentsprovider.exportInternalDataDocumentsProviderPatch - -@Suppress("unused") -@Deprecated( - "Superseded by internalDataDocumentsProviderPatch", - ReplaceWith("internalDataDocumentsProviderPatch"), -) -val changeDataDirectoryLocationPatch = bytecodePatch( - // name = "Change data directory location", - description = "Changes the data directory in the application from " + - "the app internal storage directory to /sdcard/android/data accessible by root-less devices." + - "Using this patch can cause unexpected issues with some apps.", - use = false, -) { - dependsOn(exportInternalDataDocumentsProviderPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/transformation/TransformInstructionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/transformation/TransformInstructionsPatch.kt index 6564f4f26a..8e694f103a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/transformation/TransformInstructionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/transformation/TransformInstructionsPatch.kt @@ -36,7 +36,7 @@ fun transformInstructionsPatch( } }.forEach { (classDef, methods) -> // And finally transform the methods... - val mutableClass = proxy(classDef).mutableClass + val mutableClass = mutableClassBy(classDef) methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod -> val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque()) diff --git a/patches/src/main/kotlin/app/revanced/patches/amazon/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/amazon/Fingerprints.kt index 1339149f43..35d31a5f9e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/amazon/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/amazon/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.amazon import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val deepLinkingFingerprint = fingerprint { +internal val deepLinkingFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE) returns("Z") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt index 3196adb7e1..12ded4c060 100644 --- a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt @@ -11,7 +11,7 @@ import com.android.tools.smali.dexlib2.AccessFlags // This fingerprint targets a method that returns the daily measurement count. // This method is used to determine if the user has reached the daily limit of measurements. -internal val getDailyMeasurementCountFingerprint = fingerprint { +internal val getDailyMeasurementCountFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE) returns("I") strings("dailyMeasurementCount") diff --git a/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/Fingerprints.kt index bbe71e8c78..1b42a34033 100644 --- a/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.backdrops.misc.pro import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val proUnlockFingerprint = fingerprint { +internal val proUnlockFingerprint by fingerprint { opcodes( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt b/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt index 70bbcd9fdf..19dda8b166 100644 --- a/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/ProUnlockPatch.kt @@ -12,12 +12,12 @@ val proUnlockPatch = bytecodePatch( compatibleWith("com.backdrops.wallpapers") execute { - val registerIndex = proUnlockFingerprint.patternMatch!!.endIndex - 1 + val registerIndex = proUnlockFingerprint.instructionMatches.last().index - 1 proUnlockFingerprint.method.apply { val register = getInstruction(registerIndex).registerA addInstruction( - proUnlockFingerprint.patternMatch!!.endIndex, + proUnlockFingerprint.instructionMatches.last().index, "const/4 v$register, 0x1", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/bandcamp/limitations/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/bandcamp/limitations/Fingerprints.kt index 15d306bc94..c9eccaea68 100644 --- a/patches/src/main/kotlin/app/revanced/patches/bandcamp/limitations/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/bandcamp/limitations/Fingerprints.kt @@ -2,6 +2,6 @@ package app.revanced.patches.bandcamp.limitations import app.revanced.patcher.fingerprint -internal val handlePlaybackLimitsFingerprint = fingerprint { +internal val handlePlaybackLimitsFingerprint by fingerprint { strings("track_id", "play_count") } diff --git a/patches/src/main/kotlin/app/revanced/patches/cieid/restrictions/root/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/cieid/restrictions/root/Fingerprints.kt index 387b0a0be8..6f9c9c2c63 100644 --- a/patches/src/main/kotlin/app/revanced/patches/cieid/restrictions/root/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/cieid/restrictions/root/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.cieid.restrictions.root import app.revanced.patcher.fingerprint -internal val checkRootFingerprint = fingerprint { +internal val checkRootFingerprint by fingerprint { custom { method, _ -> method.name == "onResume" && method.definingClass == "Lit/ipzs/cieid/BaseActivity;" } diff --git a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt index 0266e0344d..6184f77a2a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt @@ -2,6 +2,6 @@ package app.revanced.patches.crunchyroll.ads import app.revanced.patcher.fingerprint -internal val videoUrlReadyToStringFingerprint = fingerprint { +internal val videoUrlReadyToStringFingerprint by fingerprint { strings("VideoUrlReady(url=", ", enableAds=") } diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt index a5c56ddb05..86a236d71d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt @@ -20,7 +20,7 @@ val disableAdsPatch = bytecodePatch( // // MonetizationDebugSettings seems to be the most general setting to work fine. initializeMonetizationDebugSettingsFingerprint.method.apply { - val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex + val insertIndex = initializeMonetizationDebugSettingsFingerprint.instructionMatches.first().index val register = getInstruction(insertIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt index 9a23af8c8b..c91b909b82 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val initializeMonetizationDebugSettingsFingerprint = fingerprint { +internal val initializeMonetizationDebugSettingsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) returns("V") parameters( diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt index 833f9dd7da..715bb80def 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt @@ -14,7 +14,7 @@ val enableDebugMenuPatch = bytecodePatch( execute { initializeBuildConfigProviderFingerprint.method.apply { - val insertIndex = initializeBuildConfigProviderFingerprint.patternMatch!!.startIndex + val insertIndex = initializeBuildConfigProviderFingerprint.instructionMatches.first().index val register = getInstruction(insertIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt index 543e40b434..b1ec382943 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt @@ -11,9 +11,8 @@ import com.android.tools.smali.dexlib2.Opcode * - `isDebug`: compares "release" with "debug" <-- we want to force this to `true` */ -internal val initializeBuildConfigProviderFingerprint = fingerprint { +internal val initializeBuildConfigProviderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") opcodes(Opcode.IPUT_BOOLEAN) strings("debug", "release", "china") } diff --git a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt index e84a448baa..396f44ff05 100644 --- a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val baseModelMapperFingerprint = fingerprint { +internal val baseModelMapperFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Lcom/facebook/graphql/modelutil/BaseModelWithTree;") parameters("Ljava/lang/Class", "I", "I") @@ -17,7 +17,7 @@ internal val baseModelMapperFingerprint = fingerprint { ) } -internal val getSponsoredDataModelTemplateFingerprint = fingerprint { +internal val getSponsoredDataModelTemplateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() @@ -33,7 +33,7 @@ internal val getSponsoredDataModelTemplateFingerprint = fingerprint { } } -internal val getStoryVisibilityFingerprint = fingerprint { +internal val getStoryVisibilityFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Ljava/lang/String;") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 49d54c2b3f..abb222296a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -67,7 +67,7 @@ val hideSponsoredStoriesPatch = bytecodePatch( // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // If so, hide the story by setting the visibility to StoryVisibility.GONE. getStoryVisibilityFingerprint.method.addInstructionsWithLabels( - getStoryVisibilityFingerprint.patternMatch!!.startIndex, + getStoryVisibilityFingerprint.instructionMatches.first().index, """ instance-of v0, p0, $graphQlStoryClassDescriptor if-eqz v0, :resume_normal diff --git a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/story/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/story/Fingerprints.kt index 293d7ee82f..0a93699f01 100644 --- a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/story/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/story/Fingerprints.kt @@ -3,11 +3,11 @@ package app.revanced.patches.facebook.ads.story import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue -internal val adsInsertionFingerprint = fieldFingerprint( +internal val adsInsertionFingerprint by fieldFingerprint( fieldValue = "AdBucketDataSourceUtil\$attemptAdsInsertion\$1", ) -internal val fetchMoreAdsFingerprint = fieldFingerprint( +internal val fetchMoreAdsFingerprint by fieldFingerprint( fieldValue = "AdBucketDataSourceUtil\$attemptFetchMoreAds\$1", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/Fingerprints.kt index 4c8ee1c541..2347d1143d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/Fingerprints.kt @@ -5,7 +5,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint // Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#isBootStateOk (3.0.1) -internal val bootStateFingerprint = fingerprint { +internal val bootStateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") opcodes( @@ -30,7 +30,7 @@ internal val bootStateFingerprint = fingerprint { } // Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#createKey (3.0.1) -internal val createKeyFingerprint = fingerprint { +internal val createKeyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") strings("attestation", "SHA-256", "random", "EC", "AndroidKeyStore") diff --git a/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/Fingerprints.kt index fec7f1249f..7460461e43 100644 --- a/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/Fingerprints.kt @@ -5,7 +5,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint // Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.RootDetection#isRooted (3.0.1) -internal val rootDetectionFingerprint = fingerprint { +internal val rootDetectionFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("L") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt index ee7997a54e..6057630e69 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt @@ -14,7 +14,7 @@ val enableCustomTabsPatch = bytecodePatch( execute { launchCustomTabFingerprint.method.apply { - val checkIndex = launchCustomTabFingerprint.patternMatch!!.endIndex + 1 + val checkIndex = launchCustomTabFingerprint.instructionMatches.last().index + 1 val register = getInstruction(checkIndex).registerA replaceInstruction(checkIndex, "const/4 v$register, 0x1") diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt index 8880c010e9..387d1cbf61 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val launchCustomTabFingerprint = fingerprint { +internal val launchCustomTabFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.IPUT_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt index 6ddeb3e07f..e23ac4bc48 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.googlenews.misc.gms import app.revanced.patcher.fingerprint -internal val magazinesActivityOnCreateFingerprint = fingerprint { +internal val magazinesActivityOnCreateFingerprint by fingerprint { custom { methodDef, classDef -> methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/backup/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/backup/Fingerprints.kt index 71dda1f3ac..0c82cfe15e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/backup/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/backup/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.googlephotos.misc.backup import app.revanced.patcher.fingerprint -internal val isDCIMFolderBackupControlDisabled = fingerprint { +internal val isDCIMFolderBackupControlDisabled by fingerprint { returns("Z") strings("/dcim", "/mars_files/") } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/features/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/features/Fingerprints.kt index 95f2a3dba7..bd63a4a409 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/features/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/features/Fingerprints.kt @@ -2,6 +2,6 @@ package app.revanced.patches.googlephotos.misc.features import app.revanced.patcher.fingerprint -internal val initializeFeaturesEnumFingerprint = fingerprint { +internal val initializeFeaturesEnumFingerprint by fingerprint { strings("com.google.android.apps.photos.NEXUS_PRELOAD") } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt index f47c1a3d94..cbd720730a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.googlephotos.misc.gms import app.revanced.patcher.fingerprint -internal val homeActivityOnCreateFingerprint = fingerprint { +internal val homeActivityOnCreateFingerprint by fingerprint { custom { methodDef, classDef -> methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/Fingerprints.kt deleted file mode 100644 index 54c20a7f8c..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/Fingerprints.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.googlephotos.misc.preferences - -import app.revanced.patcher.fingerprint - -internal val backupPreferencesFingerprint = fingerprint { - returns("Lcom/google/android/apps/photos/backup/data/BackupPreferences;") - strings("backup_prefs_had_backup_only_when_charging_enabled") -} diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatch.kt deleted file mode 100644 index ea65658bda..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/preferences/RestoreHiddenBackUpWhileChargingTogglePatch.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.googlephotos.misc.preferences - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.util.indexOfFirstInstructionOrThrow -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -@Deprecated("This patch no longer works and this code will soon be deleted") -@Suppress("unused") -val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch( - description = "Restores a hidden toggle to only run backups when the device is charging." -) { - compatibleWith("com.google.android.apps.photos"("7.11.0.705590205")) - - execute { - // Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true. - backupPreferencesFingerprint.let { - it.method.apply { - val index = indexOfFirstInstructionOrThrow( - it.stringMatches!!.first().index, - Opcode.MOVE_RESULT - ) - val register = getInstruction(index).registerA - addInstruction(index + 1, "const/4 v$register, 0x1") - } - } - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt index 62e1e5f16b..431ea6c26c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.googlerecorder.restrictions import app.revanced.patcher.fingerprint -internal val onApplicationCreateFingerprint = fingerprint { +internal val onApplicationCreateFingerprint by fingerprint { strings("com.google.android.feature.PIXEL_2017_EXPERIENCE") custom { method, classDef -> if (method.name != "onCreate") return@custom false diff --git a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt index bd6921bfb0..6aec4c6000 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt @@ -14,7 +14,7 @@ val removeDeviceRestrictionsPatch = bytecodePatch( compatibleWith("com.google.android.apps.recorder") execute { - val featureStringIndex = onApplicationCreateFingerprint.stringMatches!!.first().index + val featureStringIndex = onApplicationCreateFingerprint.stringMatches.first().index onApplicationCreateFingerprint.method.apply { // Remove check for device restrictions. diff --git a/patches/src/main/kotlin/app/revanced/patches/hexeditor/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/hexeditor/ad/Fingerprints.kt index 2fa2c5b851..bed5ce6300 100644 --- a/patches/src/main/kotlin/app/revanced/patches/hexeditor/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/hexeditor/ad/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.hexeditor.ad import app.revanced.patcher.fingerprint -internal val primaryAdsFingerprint = fingerprint { +internal val primaryAdsFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("PreferencesHelper;") && method.name == "isAdsDisabled" } diff --git a/patches/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/Fingerprints.kt index 84db554572..fe15366f40 100644 --- a/patches/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.iconpackstudio.misc.pro import app.revanced.patcher.fingerprint -internal val checkProFingerprint = fingerprint { +internal val checkProFingerprint by fingerprint { returns("Z") custom { _, classDef -> classDef.endsWith("IPSPurchaseRepository;") } } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/root/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/root/Fingerprints.kt index 38f814f6d4..48c0f31ff1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/root/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/root/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.idaustria.detection.root import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val attestationSupportedCheckFingerprint = fingerprint { +internal val attestationSupportedCheckFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("V") custom { method, classDef -> @@ -12,7 +12,7 @@ internal val attestationSupportedCheckFingerprint = fingerprint { } } -internal val bootloaderCheckFingerprint = fingerprint { +internal val bootloaderCheckFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") custom { method, classDef -> @@ -21,7 +21,7 @@ internal val bootloaderCheckFingerprint = fingerprint { } } -internal val rootCheckFingerprint = fingerprint { +internal val rootCheckFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("V") custom { method, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/Fingerprints.kt index 61cd9605f1..23e2a12edd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.idaustria.detection.signature import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val spoofSignatureFingerprint = fingerprint { +internal val spoofSignatureFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE) returns("L") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/inshorts/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/inshorts/ad/Fingerprints.kt index 573bd72e35..151718de57 100644 --- a/patches/src/main/kotlin/app/revanced/patches/inshorts/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/inshorts/ad/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.inshorts.ad import app.revanced.patcher.fingerprint -internal val inshortsAdsFingerprint = fingerprint { +internal val inshortsAdsFingerprint by fingerprint { returns("V") strings("GoogleAdLoader", "exception in requestAd") } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/signature/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/signature/Fingerprints.kt index 47ebe189b3..1890ba252b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/signature/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/signature/Fingerprints.kt @@ -5,11 +5,11 @@ import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val isValidSignatureClassFingerprint = fingerprint { +internal val isValidSignatureClassFingerprint by fingerprint { strings("The provider for uri '", "' is not trusted: ") } -internal val isValidSignatureMethodFingerprint = fingerprint { +internal val isValidSignatureMethodFingerprint by fingerprint { parameters("L", "Z") returns("Z") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/irplus/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/irplus/ad/Fingerprints.kt index 30242b8d94..431bbd99a2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/irplus/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/irplus/ad/Fingerprints.kt @@ -3,9 +3,8 @@ package app.revanced.patches.irplus.ad import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val irplusAdsFingerprint = fingerprint { +internal val irplusAdsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters("L", "Z") strings("TAGGED") } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/login/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/login/Fingerprints.kt index 6345541e14..aefb36de6f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/login/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/login/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isLoggedInFingerprint = fingerprint { +internal val isLoggedInFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC, AccessFlags.FINAL) returns("Z") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/Fingerprints.kt index 5a00dc68c1..3d001bb99f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val hasPurchasedFingerprint = fingerprint { +internal val hasPurchasedFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("Z") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/Fingerprints.kt index 0dfbf5cdab..3914e00b12 100644 --- a/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val licenseValidationFingerprint = fingerprint { +internal val licenseValidationFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("Landroid/content/Context;") diff --git a/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/Fingerprints.kt index 75912318ba..396e7267d4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val verifySignatureFingerprint = fingerprint(fuzzyPatternScanThreshold = 2) { +internal val verifySignatureFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("Landroid/app/Activity;") diff --git a/patches/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/Fingerprints.kt index 1f16bb10ec..f6faf995af 100644 --- a/patches/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isFreeVersionFingerprint = fingerprint { +internal val isFreeVersionFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Ljava/lang/Boolean;") parameters("Landroid/content/Context;") diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/inbox/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/inbox/Fingerprints.kt index a2fa6329c1..814922824b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/inbox/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/inbox/Fingerprints.kt @@ -5,7 +5,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue -internal val createInboxSubTabsFingerprint = fingerprint { +internal val createInboxSubTabsFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) opcodes( @@ -22,7 +22,7 @@ internal val createInboxSubTabsFingerprint = fingerprint { } } -internal val loadInboxAdsFingerprint = fingerprint { +internal val loadInboxAdsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("V") strings( diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt deleted file mode 100644 index b9e301725c..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.messenger.inputfield - -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.patch.bytecodePatch -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -/** - * This patch will be deleted soon. - * - * Pull requests to update this patch to the latest app target are invited. - */ -@Deprecated("This patch only works with an outdated app target that is no longer fully supported by Facebook.") -@Suppress("unused") -val disableSwitchingEmojiToStickerPatch = bytecodePatch( - description = "Disables switching from emoji to sticker search mode in message input field.", -) { - compatibleWith("com.facebook.orca"("439.0.0.29.119")) - - execute { - switchMessengeInputEmojiButtonFingerprint.method.apply { - val setStringIndex = switchMessengeInputEmojiButtonFingerprint.patternMatch!!.startIndex + 2 - val targetRegister = getInstruction(setStringIndex).registerA - - replaceInstruction(setStringIndex, "const-string v$targetRegister, \"expression\"") - } - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatch.kt deleted file mode 100644 index 0d5bfd58cd..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatch.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.messenger.inputfield - -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.patch.bytecodePatch - -@Suppress("unused") -val disableTypingIndicatorPatch = bytecodePatch( - name = "Disable typing indicator", - description = "Disables the indicator while typing a message.", -) { - compatibleWith("com.facebook.orca") - - execute { - sendTypingIndicatorFingerprint.method.replaceInstruction(0, "return-void") - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/Fingerprints.kt deleted file mode 100644 index 75fd54f7da..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/Fingerprints.kt +++ /dev/null @@ -1,31 +0,0 @@ -package app.revanced.patches.messenger.inputfield - -import app.revanced.patcher.fingerprint -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.dexbacked.value.DexBackedStringEncodedValue - -internal val sendTypingIndicatorFingerprint = fingerprint { - returns("V") - parameters() - custom { method, classDef -> - method.name == "run" && - classDef.fields.any { - it.name == "__redex_internal_original_name" && - (it.initialValue as? DexBackedStringEncodedValue)?.value == "ConversationTypingContext\$sendActiveStateRunnable\$1" - } - } -} - -internal val switchMessengeInputEmojiButtonFingerprint = fingerprint { - returns("V") - parameters("L", "Z") - opcodes( - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.GOTO, - ) - strings("afterTextChanged", "expression_search") -} diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt index b84a0c7e87..2936663948 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/layout/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.messenger.layout import app.revanced.patcher.fingerprint -internal val isFacebookButtonEnabledFingerprint = fingerprint { +internal val isFacebookButtonEnabledFingerprint by fingerprint { parameters() returns("Z") strings("com.facebook.messaging.inbox.tab.plugins.core.tabtoolbarbutton." + diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt index b8dd008e4e..414dac30c7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.messenger.metaai import com.android.tools.smali.dexlib2.Opcode import app.revanced.patcher.fingerprint -internal val getMobileConfigBoolFingerprint = fingerprint { +internal val getMobileConfigBoolFingerprint by fingerprint { parameters("J") returns("Z") opcodes(Opcode.RETURN) @@ -12,12 +12,12 @@ internal val getMobileConfigBoolFingerprint = fingerprint { } } -internal val metaAIKillSwitchCheckFingerprint = fingerprint { - strings("SearchAiagentImplementationsKillSwitch") +internal val metaAIKillSwitchCheckFingerprint by fingerprint { opcodes(Opcode.CONST_WIDE) + strings("SearchAiagentImplementationsKillSwitch") } -internal val extensionMethodFingerprint = fingerprint { +internal val extensionMethodFingerprint by fingerprint { strings("REPLACED_BY_PATCH") custom { method, classDef -> method.name == EXTENSION_METHOD_NAME && classDef.type == EXTENSION_CLASS_DESCRIPTOR diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt index adee83a308..37d13e3dc5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt @@ -36,7 +36,7 @@ val removeMetaAIPatch = bytecodePatch( // Extract the common starting digits of Meta AI flag IDs from a flag found in code. val relevantDigits = with(metaAIKillSwitchCheckFingerprint) { - method.getInstruction(patternMatch!!.startIndex).wideLiteral + method.getInstruction(patternMatch.startIndex).wideLiteral }.toString().substring(0, 7) // Replace placeholder in the extension method. diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt deleted file mode 100644 index 280f448b39..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.messenger.navbar - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.messenger.metaai.removeMetaAIPatch - -@Deprecated("Superseded by removeMetaAIPatch", ReplaceWith("removeMetaAIPatch")) -@Suppress("unused") -val removeMetaAITabPatch = bytecodePatch( - description = "Removes the 'Meta AI' tab from the navbar.", -) { - dependsOn(removeMetaAIPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt index d9e1d9e0b5..a2aca9ef38 100644 --- a/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt @@ -1,13 +1,13 @@ -package app.revanced.patches.meta.ads - -import app.revanced.patcher.fingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal val adInjectorFingerprint = fingerprint { - accessFlags(AccessFlags.PRIVATE) - returns("Z") - parameters("L", "L") - strings( - "SponsoredContentController.insertItem", - ) -} +package app.revanced.patches.meta.ads + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal val adInjectorFingerprint by fingerprint { + accessFlags(AccessFlags.PRIVATE) + returns("Z") + parameters("L", "L") + strings( + "SponsoredContentController.insertItem", + ) +} diff --git a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt index 14105f762a..021e320fcb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.mifitness.misc.locale import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val syncBluetoothLanguageFingerprint = fingerprint { +internal val syncBluetoothLanguageFingerprint by fingerprint { opcodes(Opcode.MOVE_RESULT_OBJECT) custom { method, _ -> method.name == "syncBluetoothLanguage" && diff --git a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt index a2a53cabaf..676df651e0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt @@ -17,7 +17,7 @@ val forceEnglishLocalePatch = bytecodePatch( execute { syncBluetoothLanguageFingerprint.method.apply { - val resolvePhoneLocaleInstruction = syncBluetoothLanguageFingerprint.patternMatch!!.startIndex + val resolvePhoneLocaleInstruction = syncBluetoothLanguageFingerprint.instructionMatches.first().index val registerIndexToUpdate = getInstruction(resolvePhoneLocaleInstruction).registerA replaceInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/login/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/login/Fingerprints.kt index e3eee24991..d3083e8fb9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/login/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/login/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.mifitness.misc.login import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val xiaomiAccountManagerConstructorFingerprint = fingerprint { +internal val xiaomiAccountManagerConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.CONSTRUCTOR) parameters("Landroid/content/Context;", "Z") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt index 6ce0519ada..202a2d8897 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.music.ad.video import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val showVideoAdsParentFingerprint = fingerprint { +internal val showVideoAdsParentFingerprint by fingerprint { opcodes( Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt index ed4b0ead28..4a7930188f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt @@ -17,7 +17,7 @@ val hideVideoAdsPatch = bytecodePatch( execute { navigate(showVideoAdsParentFingerprint.originalMethod) - .to(showVideoAdsParentFingerprint.patternMatch!!.startIndex + 1) + .to(showVideoAdsParentFingerprint.instructionMatches.first().index + 1) .stop() .addInstruction(0, "const/4 p1, 0x0") } diff --git a/patches/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/Fingerprints.kt index 4ac10dd9bd..0883a218f2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val allowExclusiveAudioPlaybackFingerprint = fingerprint { +internal val allowExclusiveAudioPlaybackFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt index 13820d29d8..4ede1cadc3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val repeatTrackFingerprint = fingerprint { +internal val repeatTrackFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "L") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt index 89178d6aea..dd4dd3ae21 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt @@ -19,7 +19,7 @@ val permanentRepeatPatch = bytecodePatch( ) execute { - val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex + val startIndex = repeatTrackFingerprint.instructionMatches.last().index val repeatIndex = startIndex + 1 repeatTrackFingerprint.method.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/Fingerprints.kt deleted file mode 100644 index f2169744fe..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/Fingerprints.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.music.interaction.permanentshuffle - -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.AccessFlags -import app.revanced.patcher.fingerprint - -internal val disableShuffleFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("V") - parameters() - opcodes( - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL - ) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt deleted file mode 100644 index e27749495b..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.music.interaction.permanentshuffle - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("This patch no longer works and will be removed in the future.") -@Suppress("unused") -val permanentShufflePatch = bytecodePatch( - description = "Permanently remember your shuffle preference " + - "even if the playlist ends or another track is played.", - use = false, -) { - compatibleWith( - "com.google.android.apps.youtube.music"( - "6.45.54", - "6.51.53", - "7.01.53", - "7.02.52", - "7.03.52", - ), - ) - - execute { - disableShuffleFingerprint.method.addInstruction(0, "return-void") - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt index 234078c2a6..2cefcc63ce 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt @@ -4,9 +4,8 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val constructCategoryBarFingerprint = fingerprint { +internal val constructCategoryBarFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters("Landroid/content/Context;", "L", "L", "L") opcodes( Opcode.IPUT_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt index 8c5ed8139c..626683376f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt @@ -20,7 +20,7 @@ val hideCategoryBar = bytecodePatch( execute { constructCategoryBarFingerprint.method.apply { - val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex + val insertIndex = constructCategoryBarFingerprint.instructionMatches.first().index val register = getInstruction(insertIndex - 1).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt index 29558ab4be..42dbc6bcbe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val hideGetPremiumFingerprint = fingerprint { +internal val hideGetPremiumFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() @@ -16,7 +16,7 @@ internal val hideGetPremiumFingerprint = fingerprint { strings("FEmusic_history", "FEmusic_offline") } -internal val membershipSettingsFingerprint = fingerprint { +internal val membershipSettingsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/CharSequence;") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt index e45a90426f..380197e3c1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt @@ -20,7 +20,7 @@ val hideGetPremiumPatch = bytecodePatch( execute { hideGetPremiumFingerprint.method.apply { - val insertIndex = hideGetPremiumFingerprint.patternMatch!!.endIndex + val insertIndex = hideGetPremiumFingerprint.instructionMatches.last().index val setVisibilityInstruction = getInstruction(insertIndex) val getPremiumViewRegister = setVisibilityInstruction.registerC diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/Fingerprints.kt index f3c96dc44a..7012360a51 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/Fingerprints.kt @@ -4,9 +4,8 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val pivotBarConstructorFingerprint = fingerprint { +internal val pivotBarConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters("L", "Z") opcodes( Opcode.CHECK_CAST, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt index 12b81b9a0d..1812576cff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt @@ -28,7 +28,7 @@ val removeUpgradeButtonPatch = bytecodePatch( execute { pivotBarConstructorFingerprint.method.apply { val pivotBarElementFieldReference = - getInstruction(pivotBarConstructorFingerprint.patternMatch!!.endIndex - 1) + getInstruction(pivotBarConstructorFingerprint.instructionMatches.last().index - 1) .getReference() val register = getInstruction(0).registerC @@ -42,7 +42,7 @@ val removeUpgradeButtonPatch = bytecodePatch( iput-object v0, v$register, $pivotBarElementFieldReference """.toInstructions().toMutableList() - val endIndex = pivotBarConstructorFingerprint.patternMatch!!.endIndex + val endIndex = pivotBarConstructorFingerprint.instructionMatches.last().index // Replace the instruction to retain the label at given index. replaceInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/androidauto/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/androidauto/Fingerprints.kt index 97dea56502..30c0ec0cbb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/androidauto/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/androidauto/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.music.misc.androidauto import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val checkCertificateFingerprint = fingerprint { +internal val checkCertificateFingerprint by fingerprint { returns("Z") parameters("Ljava/lang/String;") strings( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/Fingerprints.kt index e1cf24e1a2..7e408aaa91 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val backgroundPlaybackDisableFingerprint = fingerprint { +internal val backgroundPlaybackDisableFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("L") @@ -21,7 +21,7 @@ internal val backgroundPlaybackDisableFingerprint = fingerprint { ) } -internal val kidsBackgroundPlaybackPolicyControllerFingerprint = fingerprint { +internal val kidsBackgroundPlaybackPolicyControllerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("I", "L", "Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt index 1e1a43f9aa..869174c45f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt @@ -1,10 +1,13 @@ package app.revanced.patches.music.misc.extension.hooks +import app.revanced.patcher.string import app.revanced.patches.shared.misc.extension.extensionHook internal val applicationInitHook = extensionHook { returns("V") parameters() - strings("activity") + instructions( + string("activity") + ) custom { method, _ -> method.name == "onCreate" } } diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt index 7131e143df..9ad55f01d6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.misc.gms import app.revanced.patcher.fingerprint -internal val musicActivityOnCreateFingerprint = fingerprint { +internal val musicActivityOnCreateFingerprint by fingerprint { returns("V") parameters("Landroid/os/Bundle;") custom { method, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/Fingerprints.kt index abf19cc958..22cf63b849 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val playerRequestConstructorFingerprint = fingerprint { +internal val playerRequestConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) strings("player") } @@ -12,7 +12,7 @@ internal val playerRequestConstructorFingerprint = fingerprint { /** * Matches using the class found in [playerRequestConstructorFingerprint]. */ -internal val createPlayerRequestBodyFingerprint = fingerprint { +internal val createPlayerRequestBodyFingerprint by fingerprint { parameters("L") returns("V") opcodes( @@ -26,7 +26,7 @@ internal val createPlayerRequestBodyFingerprint = fingerprint { /** * Used to get a reference to other clientInfo fields. */ -internal val setClientInfoFieldsFingerprint = fingerprint { +internal val setClientInfoFieldsFingerprint by fingerprint { returns("L") strings("Google Inc.") } @@ -34,6 +34,6 @@ internal val setClientInfoFieldsFingerprint = fingerprint { /** * Used to get a reference to the clientInfo and clientInfo.clientVersion field. */ -internal val setClientInfoClientVersionFingerprint = fingerprint { +internal val setClientInfoClientVersionFingerprint by fingerprint { strings("10.29") } diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofClientPatch.kt index e6fb8e3fe3..6bc73afd20 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofClientPatch.kt @@ -44,7 +44,7 @@ val spoofClientPatch = bytecodePatch( val createPlayerRequestBodyMatch = createPlayerRequestBodyFingerprint.match(playerRequestClass) val clientInfoContainerClass = createPlayerRequestBodyMatch.method - .getInstruction(createPlayerRequestBodyMatch.patternMatch!!.startIndex) + .getInstruction(createPlayerRequestBodyMatch.instructionMatches.first().index) .getReference()!!.type val clientInfoField = setClientInfoClientVersionFingerprint.method.instructions.first { @@ -61,7 +61,7 @@ val spoofClientPatch = bytecodePatch( val clientModelField = setClientInfoFieldInstructions[5] val osVersionField = setClientInfoFieldInstructions[7] val clientVersionField = setClientInfoClientVersionFingerprint.method - .getInstruction(setClientInfoClientVersionFingerprint.stringMatches!!.first().index + 1) + .getInstruction(setClientInfoClientVersionFingerprint.stringMatches.first().index + 1) .getReference() // Helper method to spoof the client info. @@ -101,7 +101,7 @@ val spoofClientPatch = bytecodePatch( } createPlayerRequestBodyMatch.method.apply { - val checkCastIndex = createPlayerRequestBodyMatch.patternMatch!!.startIndex + val checkCastIndex = createPlayerRequestBodyMatch.instructionMatches.first().index val clientInfoContainerRegister = getInstruction(checkCastIndex).registerA addInstruction(checkCastIndex + 1, "invoke-static {v$clientInfoContainerRegister}, $spoofClientInfoMethod") diff --git a/patches/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/Fingerprints.kt index 6bc4c21e5c..a118f681a4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/myexpenses/misc/pro/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.myexpenses.misc.pro import app.revanced.patcher.fingerprint -internal val isEnabledFingerprint = fingerprint { +internal val isEnabledFingerprint by fingerprint { returns("Z") strings("feature", "feature.licenceStatus") } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/myfitnesspal/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/myfitnesspal/ads/Fingerprints.kt index 160e2db274..6afea3462f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/myfitnesspal/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/myfitnesspal/ads/Fingerprints.kt @@ -3,14 +3,14 @@ package app.revanced.patches.myfitnesspal.ads import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val isPremiumUseCaseImplFingerprint = fingerprint { +internal val isPremiumUseCaseImplFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) custom { method, classDef -> classDef.endsWith("IsPremiumUseCaseImpl;") && method.name == "doWork" } } -internal val mainActivityNavigateToNativePremiumUpsellFingerprint = fingerprint { +internal val mainActivityNavigateToNativePremiumUpsellFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") custom { method, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt index f4f5d48c02..bf070df088 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nfctoolsse/misc/pro/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.nfctoolsse.misc.pro import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isLicenseRegisteredFingerprint = fingerprint { +internal val isLicenseRegisteredFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") strings("kLicenseCheck") diff --git a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt index 109b973e0c..4039558061 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val jwPlayerConfigFingerprint = fingerprint { +internal val jwPlayerConfigFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) custom { methodDef, classDef -> classDef.type == "Lcom/jwplayer/pub/api/configuration/PlayerConfig${'$'}Builder;" && methodDef.name == "advertisingConfig" } } -internal val screenMapperFingerprint = fingerprint { +internal val screenMapperFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Lnl/nu/android/bff/domain/models/screen/ScreenEntity;") parameters("Lnl/nu/performance/api/client/objects/Screen;") @@ -27,7 +27,7 @@ internal val screenMapperFingerprint = fingerprint { } } -internal val nextPageRepositoryImplFingerprint = fingerprint { +internal val nextPageRepositoryImplFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("Lnl/nu/android/bff/domain/models/Page;") parameters("Lnl/nu/performance/api/client/PacResponse;", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/nunl/firebase/SpoofCertificatePatch.kt b/patches/src/main/kotlin/app/revanced/patches/nunl/firebase/SpoofCertificatePatch.kt index 65944c4c1f..1e5890a859 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nunl/firebase/SpoofCertificatePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nunl/firebase/SpoofCertificatePatch.kt @@ -11,7 +11,9 @@ val spoofCertificatePatch = bytecodePatch( compatibleWith("nl.sanomamedia.android.nu") execute { - getFingerprintHashForPackageFingerprints.forEach { fingerprint -> + getFingerprintHashForPackageFingerprints.forEach { fingerprintBuilder -> + val fingerprint by fingerprintBuilder + fingerprint.method.returnEarly("eae41fc018df2731a9b6ae1ac327da44a288667b") } } diff --git a/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/Fingerprints.kt deleted file mode 100644 index e2bffa451a..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/Fingerprints.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.nyx.misc.pro - -import app.revanced.patcher.fingerprint - -internal val checkProFingerprint = fingerprint { - custom { method, classDef -> - classDef.endsWith("BillingManager;") && method.name == "isProVersion" - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt b/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt deleted file mode 100644 index 179e745e08..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/nyx/misc/pro/UnlockProPatch.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.nyx.misc.pro - -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("This patch will be removed in the future.") -@Suppress("unused") -val unlockProPatch = bytecodePatch { - compatibleWith("com.awedea.nyx") - - execute { - checkProFingerprint.method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """, - ) - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/openinghours/misc/fix/crash/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/openinghours/misc/fix/crash/Fingerprints.kt index 69463c510d..56fcf73d74 100644 --- a/patches/src/main/kotlin/app/revanced/patches/openinghours/misc/fix/crash/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/openinghours/misc/fix/crash/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.openinghours.misc.fix.crash import app.revanced.patcher.fingerprint -internal val setPlaceFingerprint = fingerprint { +internal val setPlaceFingerprint by fingerprint { returns("V") parameters("Lde/simon/openinghours/models/Place;") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/pandora/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/pandora/ads/Fingerprints.kt index e3f432e16d..9e0a801478 100644 --- a/patches/src/main/kotlin/app/revanced/patches/pandora/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/pandora/ads/Fingerprints.kt @@ -2,13 +2,13 @@ package app.revanced.patches.pandora.ads import app.revanced.patcher.fingerprint -internal val getIsAdSupportedFingerprint = fingerprint { +internal val getIsAdSupportedFingerprint by fingerprint { custom { method, classDef -> method.name == "getIsAdSupported" && classDef.endsWith("UserData;") } } -internal val requestAudioAdFingerprint = fingerprint { +internal val requestAudioAdFingerprint by fingerprint { custom { method, classDef -> method.name == "requestAudioAdFromAdSDK" && classDef.endsWith("ContentServiceOpsImpl;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/pandora/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/pandora/misc/Fingerprints.kt index 2a14e0ed1b..4c6e675fca 100644 --- a/patches/src/main/kotlin/app/revanced/patches/pandora/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/pandora/misc/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.pandora.misc import app.revanced.patcher.fingerprint -internal val skipLimitBehaviorFingerprint = fingerprint { +internal val skipLimitBehaviorFingerprint by fingerprint { custom { method, classDef -> method.name == "getSkipLimitBehavior" && classDef.endsWith("UserData;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/Fingerprints.kt index 90c0bbb919..d37351f8e2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/deviceid/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.photomath.detection.deviceid import com.android.tools.smali.dexlib2.Opcode import app.revanced.patcher.fingerprint -internal val getDeviceIdFingerprint = fingerprint { +internal val getDeviceIdFingerprint by fingerprint { returns("Ljava/lang/String;") parameters() opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt index c6563270e1..d1b24e5546 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.photomath.detection.signature import com.android.tools.smali.dexlib2.Opcode import app.revanced.patcher.fingerprint -internal val checkSignatureFingerprint = fingerprint { +internal val checkSignatureFingerprint by fingerprint { opcodes( Opcode.CONST_STRING, Opcode.INVOKE_STATIC, diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt index 00b47e5161..96eb3ba0fb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt @@ -10,7 +10,7 @@ val signatureDetectionPatch = bytecodePatch( ) { execute { - val replacementIndex = checkSignatureFingerprint.patternMatch!!.endIndex + val replacementIndex = checkSignatureFingerprint.instructionMatches.last().index val checkRegister = checkSignatureFingerprint.method.getInstruction(replacementIndex).registerA checkSignatureFingerprint.method.replaceInstruction(replacementIndex, "const/4 v$checkRegister, 0x1") diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/annoyances/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/annoyances/Fingerprints.kt index 301f2f9a52..694573b433 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/annoyances/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/annoyances/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val hideUpdatePopupFingerprint = fingerprint { +internal val hideUpdatePopupFingerprint by fingerprint { accessFlags(AccessFlags.FINAL, AccessFlags.PUBLIC) returns("V") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/bookpoint/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/bookpoint/Fingerprints.kt index 6722f4223e..d0565792d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/bookpoint/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/bookpoint/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.photomath.misc.unlock.bookpoint import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isBookpointEnabledFingerprint = fingerprint { +internal val isBookpointEnabledFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/plus/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/plus/Fingerprints.kt index f6c282cbd4..bc153d400c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/plus/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/misc/unlock/plus/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.photomath.misc.unlock.plus import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isPlusUnlockedFingerprint = fingerprint{ +internal val isPlusUnlockedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") strings("genius") diff --git a/patches/src/main/kotlin/app/revanced/patches/piccomafr/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/piccomafr/misc/Fingerprints.kt index 8c2d579ef5..199cd01af7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/piccomafr/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/piccomafr/misc/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.piccomafr.misc import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val getAndroidIdFingerprint = fingerprint { +internal val getAndroidIdFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters("Landroid/content/Context;") diff --git a/patches/src/main/kotlin/app/revanced/patches/piccomafr/tracking/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/piccomafr/tracking/Fingerprints.kt index 794f21bcb6..e757223dd3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/piccomafr/tracking/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/piccomafr/tracking/Fingerprints.kt @@ -3,19 +3,18 @@ package app.revanced.patches.piccomafr.tracking import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val appMeasurementFingerprint = fingerprint { +internal val appMeasurementFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") strings("config/app/", "Fetching remote configuration") } -internal val facebookSDKFingerprint = fingerprint { +internal val facebookSDKFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - returns("V") strings("instagram.com", "facebook.com") } -internal val firebaseInstallFingerprint = fingerprint { +internal val firebaseInstallFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE) strings( "https://%s/%s/%s", diff --git a/patches/src/main/kotlin/app/revanced/patches/pixiv/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/pixiv/ads/Fingerprints.kt index 3e2addaa06..825a834b62 100644 --- a/patches/src/main/kotlin/app/revanced/patches/pixiv/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/pixiv/ads/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.pixiv.ads import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val shouldShowAdsFingerprint = fingerprint { +internal val shouldShowAdsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") custom { methodDef, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt index ac3a1c43a5..8af0fc2737 100644 --- a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val enterServerInsertedAdBreakStateFingerprint = fingerprint { +internal val enterServerInsertedAdBreakStateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) parameters("Lcom/amazon/avod/fsm/Trigger;") returns("V") @@ -19,7 +19,7 @@ internal val enterServerInsertedAdBreakStateFingerprint = fingerprint { } } -internal val doTriggerFingerprint = fingerprint { +internal val doTriggerFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED) returns("V") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/rar/misc/annoyances/purchasereminder/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/rar/misc/annoyances/purchasereminder/Fingerprints.kt index a4d2c9e221..d63bbce862 100644 --- a/patches/src/main/kotlin/app/revanced/patches/rar/misc/annoyances/purchasereminder/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/rar/misc/annoyances/purchasereminder/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.rar.misc.annoyances.purchasereminder import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val showReminderFingerprint = fingerprint { +internal val showReminderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("V") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/ad/comments/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/ad/comments/Fingerprints.kt index c99df5707a..91ea04763e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/ad/comments/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/ad/comments/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.ad.comments import app.revanced.patcher.fingerprint -internal val hideCommentAdsFingerprint = fingerprint { +internal val hideCommentAdsFingerprint by fingerprint { strings( "link", // CommentPageRepository is not returning a link object diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/ad/general/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/ad/general/Fingerprints.kt index e7dd789123..93310ce7e9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/ad/general/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/ad/general/Fingerprints.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.ad.general import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val adPostFingerprint = fingerprint { +internal val adPostFingerprint by fingerprint { returns("V") // "children" are present throughout multiple versions strings("children") custom { _, classDef -> classDef.endsWith("Listing;") } } -internal val newAdPostFingerprint = fingerprint { +internal val newAdPostFingerprint by fingerprint { opcodes(Opcode.INVOKE_VIRTUAL) strings("chain", "feedElement") custom { _, classDef -> classDef.sourceFile == "AdElementConverter.kt" } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt index bb87c21148..b3c0a957b8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt @@ -2,10 +2,10 @@ package app.revanced.patches.reddit.customclients.baconreader.api import app.revanced.patcher.fingerprint -internal val getAuthorizationUrlFingerprint = fingerprint { +internal val getAuthorizationUrlFingerprint by fingerprint { strings("client_id=zACVn0dSFGdWqQ") } -internal val getClientIdFingerprint = fingerprint { +internal val getClientIdFingerprint by fingerprint { strings("client_id=zACVn0dSFGdWqQ") custom { method, classDef -> if (!classDef.endsWith("RedditOAuth;")) return@custom false @@ -14,6 +14,6 @@ internal val getClientIdFingerprint = fingerprint { } } -internal val requestTokenFingerprint = fingerprint { +internal val requestTokenFingerprint by fingerprint { strings("zACVn0dSFGdWqQ", "kDm2tYpu9DqyWFFyPlNcXGEni4k") // App ID and secret. } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/ads/Fingerprints.kt index 618e2f1456..3462a91942 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/ads/Fingerprints.kt @@ -2,10 +2,10 @@ package app.revanced.patches.reddit.customclients.boostforreddit.ads import app.revanced.patcher.fingerprint -internal val maxMediationFingerprint = fingerprint { +internal val maxMediationFingerprint by fingerprint { strings("MaxMediation: Attempting to initialize SDK") } -internal val admobMediationFingerprint = fingerprint { +internal val admobMediationFingerprint by fingerprint { strings("AdmobMediation: Attempting to initialize SDK") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/Fingerprints.kt index cc06fd3968..a6d4543043 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/Fingerprints.kt @@ -2,11 +2,11 @@ package app.revanced.patches.reddit.customclients.boostforreddit.api import app.revanced.patcher.fingerprint -internal val buildUserAgentFingerprint = fingerprint { +internal val buildUserAgentFingerprint by fingerprint { strings("%s:%s:%s (by /u/%s)") } -internal val getClientIdFingerprint = fingerprint { +internal val getClientIdFingerprint by fingerprint { custom { method, classDef -> if (!classDef.endsWith("Credentials;")) return@custom false diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt index a2b1530b8b..f7a3ea815b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt @@ -2,6 +2,6 @@ package app.revanced.patches.reddit.customclients.boostforreddit.fix.downloads import app.revanced.patcher.fingerprint -internal val downloadAudioFingerprint = fingerprint { +internal val downloadAudioFingerprint by fingerprint { strings("/DASH_audio.mp4", "/audio") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt index 8cb3f55186..c5b548f93f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt @@ -19,7 +19,7 @@ val fixAudioMissingInDownloadsPatch = bytecodePatch( ) downloadAudioFingerprint.method.apply { - downloadAudioFingerprint.stringMatches!!.forEach { match -> + downloadAudioFingerprint.stringMatches.forEach { match -> val replacement = endpointReplacements[match.string] val register = getInstruction(match.index).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/Fingerprints.kt index 665dba5a40..e690af53d9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/Fingerprints.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.customclients.boostforreddit.fix.slink import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val getOAuthAccessTokenFingerprint = fingerprint { +internal val getOAuthAccessTokenFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Ljava/lang/String") strings("access_token") custom { method, _ -> method.definingClass == "Lnet/dean/jraw/http/oauth/OAuthData;" } } -internal val handleNavigationFingerprint = fingerprint { +internal val handleNavigationFingerprint by fingerprint { strings( "android.intent.action.SEARCH", "subscription", diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/Fingerprints.kt index 4bce1362c2..0d7f124f61 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/api/Fingerprints.kt @@ -2,6 +2,6 @@ package app.revanced.patches.reddit.customclients.infinityforreddit.api import app.revanced.patcher.fingerprint -internal val apiUtilsFingerprint = fingerprint { +internal val apiUtilsFingerprint by fingerprint { strings("native-lib") } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/subscription/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/subscription/Fingerprints.kt index 36fe062796..22842f81ec 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/subscription/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/infinityforreddit/subscription/Fingerprints.kt @@ -1,15 +1,14 @@ package app.revanced.patches.reddit.customclients.infinityforreddit.subscription import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal -internal val billingClientOnServiceConnectedFingerprint = fingerprint { +internal val billingClientOnServiceConnectedFingerprint by fingerprint { strings("Billing service connected") } -internal val startSubscriptionActivityFingerprint = fingerprint { - literal { - // Intent start flag only used in the subscription activity - 0x10008000 - } +internal val startSubscriptionActivityFingerprint by fingerprint { + instructions( + literal(0x10008000) // Intent start flag only used in the subscription activity + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/Fingerprints.kt index 465faf1200..e136d57ec7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/ads/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.customclients.joeyforreddit.ads import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isAdFreeUserFingerprint = fingerprint { +internal val isAdFreeUserFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Z") strings("AD_FREE_USER") diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/Fingerprints.kt index e6c591748c..c6c5c0abb7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val authUtilityUserAgentFingerprint = fingerprint { +internal val authUtilityUserAgentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Ljava/lang/String;") opcodes(Opcode.APUT_OBJECT) @@ -13,7 +13,7 @@ internal val authUtilityUserAgentFingerprint = fingerprint { } } -internal val getClientIdFingerprint = fingerprint { +internal val getClientIdFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("L") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/Fingerprints.kt index 76343a5309..d8ae7417a7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val piracyDetectionFingerprint = fingerprint { +internal val piracyDetectionFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("V") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt index 5b3029094f..a976c7b50d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt @@ -8,15 +8,15 @@ internal fun baseClientIdFingerprint(string: String) = fingerprint { strings("yyOCBp.RHJhDKd", string) } -internal val basicAuthorizationFingerprint = baseClientIdFingerprint( +internal val basicAuthorizationFingerprint by baseClientIdFingerprint( string = "fJOxVwBUyo*=f: - val clientIdIndex = fingerprint.stringMatches!!.first().index + val clientIdIndex = fingerprint.stringMatches.first().index fingerprint.method.apply { val clientIdRegister = getInstruction(clientIdIndex).registerA @@ -45,7 +45,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") { setRemoteConfigFingerprint.method.addInstructions(0, "return-void") // Prevent OAuth login being disabled remotely. - val checkIsOAuthRequestIndex = redditCheckDisableAPIFingerprint.patternMatch!!.startIndex + val checkIsOAuthRequestIndex = redditCheckDisableAPIFingerprint.instructionMatches.first().index redditCheckDisableAPIFingerprint.method.apply { val returnNextChain = getInstruction(checkIsOAuthRequestIndex).target diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/Fingerprints.kt index 4ff8be4615..79f3179afe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/slide/api/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.customclients.slide.api import app.revanced.patcher.fingerprint -internal val getClientIdFingerprint = fingerprint { +internal val getClientIdFingerprint by fingerprint { custom { method, classDef -> if (!classDef.endsWith("Credentials;")) return@custom false diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt index e055493bdd..0290c185be 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.customclients.sync.ads import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val isAdsEnabledFingerprint = fingerprint { +internal val isAdsEnabledFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") strings("SyncIapHelper") diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/Fingerprints.kt index e83e914d75..46a98af1af 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/Fingerprints.kt @@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.Reference -internal val piracyDetectionFingerprint = fingerprint { +internal val piracyDetectionFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/annoyances/startup/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/annoyances/startup/Fingerprints.kt index 21c788a89c..0e243f97c1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/annoyances/startup/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/annoyances/startup/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.annoyances. import app.revanced.patcher.fingerprint -internal val mainActivityOnCreateFingerprint = fingerprint { +internal val mainActivityOnCreateFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("MainActivity;") && method.name == "onCreate" } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt index c7902b1f4d..41e7d5f928 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt @@ -2,18 +2,18 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.api import app.revanced.patcher.fingerprint -internal val getAuthorizationStringFingerprint = fingerprint { +internal val getAuthorizationStringFingerprint by fingerprint { strings("authorize.compact?client_id") } -internal val getBearerTokenFingerprint = fingerprint { +internal val getBearerTokenFingerprint by fingerprint { strings("Basic") } -internal val getUserAgentFingerprint = fingerprint { +internal val getUserAgentFingerprint by fingerprint { strings("android:com.laurencedawson.reddit_sync") } -internal val imgurImageAPIFingerprint = fingerprint { +internal val imgurImageAPIFingerprint by fingerprint { strings("https://imgur-apiv3.p.rapidapi.com/3/image") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt index 64d6ca1117..1858ab7f35 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt @@ -31,7 +31,7 @@ val spoofClientPatch = spoofClientPatch( returnEarly("Basic $auth") val occurrenceIndex = - getAuthorizationStringFingerprint.stringMatches!!.first().index + getAuthorizationStringFingerprint.stringMatches.first().index getAuthorizationStringFingerprint.method.apply { val authorizationStringInstruction = getInstruction(occurrenceIndex) @@ -65,7 +65,7 @@ val spoofClientPatch = spoofClientPatch( // region Patch Imgur API URL. imgurImageAPIFingerprint.let { - val apiUrlIndex = it.stringMatches!!.first().index + val apiUrlIndex = it.stringMatches.first().index it.method.replaceInstruction( apiUrlIndex, "const-string v1, \"https://api.imgur.com/3/image\"", diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/Fingerprints.kt index f7287fcc39..641a3e99e1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/Fingerprints.kt @@ -2,11 +2,11 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.slink import app.revanced.patcher.fingerprint -internal val linkHelperOpenLinkFingerprint = fingerprint { +internal val linkHelperOpenLinkFingerprint by fingerprint { strings("Link title: ") } -internal val setAuthorizationHeaderFingerprint = fingerprint { +internal val setAuthorizationHeaderFingerprint by fingerprint { returns("Ljava/util/HashMap;") strings("Authorization", "bearer ") custom { method, _ -> method.definingClass == "Lcom/laurencedawson/reddit_sync/singleton/a;" } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt index 7a64031f16..6ed3118cb1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.thumbna import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val customImageViewLoadFingerprint = fingerprint { +internal val customImageViewLoadFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) parameters("Ljava/lang/String;", "Z", "Z", "I", "I") custom { _, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt index 4bac74de77..94a9adb2ba 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt @@ -9,28 +9,28 @@ internal fun userEndpointFingerprint(source: String, accessFlags: Set - fingerprint.stringMatches!!.first().index to fingerprint.method + fingerprint.stringMatches.first().index to fingerprint.method }.forEach { (userPathStringIndex, method) -> val userPathStringInstruction = method.getInstruction(userPathStringIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt index 9ddeaf9cf5..9da9830cff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.video import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val parseRedditVideoNetworkResponseFingerprint = fingerprint { +internal val parseRedditVideoNetworkResponseFingerprint by fingerprint { opcodes( Opcode.NEW_INSTANCE, Opcode.IGET_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 64c33f308b..cb4fa24651 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -24,9 +24,9 @@ val fixVideoDownloadsPatch = bytecodePatch( ) execute { - val scanResult = parseRedditVideoNetworkResponseFingerprint.patternMatch!! - val newInstanceIndex = scanResult.startIndex - val invokeDirectIndex = scanResult.endIndex - 1 + val scanResult = parseRedditVideoNetworkResponseFingerprint.instructionMatches + val newInstanceIndex = scanResult.first().index + val invokeDirectIndex = scanResult.last().index - 1 val buildResponseInstruction = parseRedditVideoNetworkResponseFingerprint.method.getInstruction(invokeDirectIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt deleted file mode 100644 index 28ad4a0dbe..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.reddit.customclients.syncforreddit.fix.video - -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated( - message = "Patch was move to a different package", - ReplaceWith("app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.video.fixVideoDownloadsPatch") -) -@Suppress("unused") -val fixVideoDownloadsPatch = bytecodePatch { - dependsOn(app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.video.fixVideoDownloadsPatch) - - compatibleWith( - "com.laurencedawson.reddit_sync", - "com.laurencedawson.reddit_sync.pro", - "com.laurencedawson.reddit_sync.dev", - ) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/Fingerprints.kt index 09fe16247e..3127bbbc6d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/disablescreenshotpopup/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.layout.disablescreenshotpopup import app.revanced.patcher.fingerprint -internal val disableScreenshotPopupFingerprint = fingerprint { +internal val disableScreenshotPopupFingerprint by fingerprint { returns("V") parameters("Landroidx/compose/runtime/", "I") custom { method, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/Fingerprints.kt index 2eac1cbe26..803192a909 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.layout.premiumicon import app.revanced.patcher.fingerprint -internal val hasPremiumIconAccessFingerprint = fingerprint { +internal val hasPremiumIconAccessFingerprint by fingerprint { returns("Z") custom { method, classDef -> classDef.endsWith("MyAccount;") && method.name == "isPremiumSubscriber" diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt index 992ff27e5f..5b8652a6f8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt @@ -20,9 +20,3 @@ val unlockPremiumIconsPatch = bytecodePatch( ) } } - -@Deprecated("Patch was renamed", ReplaceWith("unlockPremiumIconsPatch")) -@Suppress("unused") -val unlockPremiumIconPatch = bytecodePatch{ - dependsOn(unlockPremiumIconsPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/Fingerprints.kt index 3381fd2bb2..b861b79408 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.misc.tracking.url import app.revanced.patcher.fingerprint -internal val shareLinkFormatterFingerprint = fingerprint { +internal val shareLinkFormatterFingerprint by fingerprint { custom { _, classDef -> classDef.startsWith("Lcom/reddit/sharing/") && classDef.sourceFile == "UrlUtil.kt" } diff --git a/patches/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/Fingerprints.kt index f7efe3103f..f1b352b037 100644 --- a/patches/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/serviceportalbund/detection/root/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.serviceportalbund.detection.root import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val rootDetectionFingerprint = fingerprint { +internal val rootDetectionFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("V") custom { _, classDef -> diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt index df927dd4a7..a83f3b1d2c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt @@ -1,11 +1,17 @@ package app.revanced.patches.shared import app.revanced.patcher.fingerprint +import app.revanced.patcher.string -internal val castContextFetchFingerprint = fingerprint { - strings("Error fetching CastContext.") +internal val castContextFetchFingerprint by fingerprint { + instructions( + string("Error fetching CastContext.") + ) } -internal val primeMethodFingerprint = fingerprint { - strings("com.google.android.GoogleCamera", "com.android.vending") +internal val primeMethodFingerprint by fingerprint { + instructions( + string("com.android.vending"), + string("com.google.android.GoogleCamera") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt index 0eabd2f547..b63e5c04ad 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/checks/Fingerprints.kt @@ -2,10 +2,10 @@ package app.revanced.patches.shared.misc.checks import app.revanced.patcher.fingerprint -internal val patchInfoFingerprint = fingerprint { +internal val patchInfoFingerprint by fingerprint { custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo;" } } -internal val patchInfoBuildFingerprint = fingerprint { +internal val patchInfoBuildFingerprint by fingerprint { custom { _, classDef -> classDef.type == "Lapp/revanced/extension/shared/checks/PatchInfo\$Build;" } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/Fingerprints.kt index 58cc5082f1..b61a6763da 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.shared.misc.extension import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val revancedUtilsPatchesVersionFingerprint = fingerprint { +internal val revancedUtilsPatchesVersionFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Ljava/lang/String;") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt index 129073b7d4..531a1b2f4f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt @@ -2,10 +2,9 @@ package app.revanced.patches.shared.misc.extension import app.revanced.patcher.Fingerprint import app.revanced.patcher.FingerprintBuilder +import app.revanced.patcher.FingerprintDelegate import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.fingerprint import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.iface.Method @@ -21,7 +20,7 @@ internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/ */ fun sharedExtensionPatch( extensionName: String, - vararg hooks: ExtensionHook, + vararg hooks: () -> ExtensionHook, ) = bytecodePatch { dependsOn(sharedExtensionPatch(*hooks)) @@ -35,19 +34,18 @@ fun sharedExtensionPatch( * commonly for the onCreate method of exported activities. */ fun sharedExtensionPatch( - vararg hooks: ExtensionHook, + vararg hooks: () -> ExtensionHook, ) = bytecodePatch { extendWith("extensions/shared.rve") execute { - if (classes.none { EXTENSION_CLASS_DESCRIPTOR == it.type }) { - throw PatchException("Shared extension is not available. This patch can not succeed without it.") - } + // Verify the extension class exists. + classBy(EXTENSION_CLASS_DESCRIPTOR) } finalize { // The hooks are made in finalize to ensure that the context is hooked before any other patches. - hooks.forEach { hook -> hook(EXTENSION_CLASS_DESCRIPTOR) } + hooks.forEach { hook -> hook()(EXTENSION_CLASS_DESCRIPTOR) } // Modify Utils method to include the patches release version. revancedUtilsPatchesVersionFingerprint.method.apply { @@ -113,4 +111,7 @@ fun extensionHook( insertIndexResolver: ((Method) -> Int) = { 0 }, contextRegisterResolver: (Method) -> String = { "p0" }, fingerprintBuilderBlock: FingerprintBuilder.() -> Unit, -) = extensionHook(insertIndexResolver, contextRegisterResolver, fingerprint(block = fingerprintBuilderBlock)) +) = { + val fingerprint by FingerprintDelegate(block = fingerprintBuilderBlock) + ExtensionHook(fingerprint, insertIndexResolver, contextRegisterResolver) +} diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt index 80d041ada8..8b784b2db6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val canScrollVerticallyFingerprint = fingerprint { +internal val canScrollVerticallyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt index a01839c100..b4bc540a9e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt @@ -10,15 +10,17 @@ val verticalScrollPatch = bytecodePatch( ) { execute { - canScrollVerticallyFingerprint.method.apply { - val moveResultIndex = canScrollVerticallyFingerprint.patternMatch!!.endIndex - val moveResultRegister = getInstruction(moveResultIndex).registerA + canScrollVerticallyFingerprint.let { + it.method.apply { + val moveResultIndex = it.instructionMatches.last().index + val moveResultRegister = getInstruction(moveResultIndex).registerA - val insertIndex = moveResultIndex + 1 - addInstruction( - insertIndex, - "const/4 v$moveResultRegister, 0x0", - ) + val insertIndex = moveResultIndex + 1 + addInstruction( + insertIndex, + "const/4 v$moveResultRegister, 0x0", + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt index b5f613d541..355a07ba81 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt @@ -3,15 +3,15 @@ package app.revanced.patches.shared.misc.gms import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId" - -internal val gmsCoreSupportFingerprint = fingerprint { - custom { _, classDef -> - classDef.endsWith("GmsCoreSupport;") +internal val gmsCoreSupportFingerprint by fingerprint { + accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) + custom { method, classDef -> + method.name == "getGmsCoreVendorGroupId" + && classDef.endsWith("/GmsCoreSupport;") } } -internal val googlePlayUtilityFingerprint = fingerprint { +internal val googlePlayUtilityFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("I") parameters("L", "I") @@ -22,7 +22,7 @@ internal val googlePlayUtilityFingerprint = fingerprint { ) } -internal val serviceCheckFingerprint = fingerprint { +internal val serviceCheckFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("V") parameters("L", "I") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt index d5260653ac..c7e4d4b04f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt @@ -78,7 +78,7 @@ fun gmsCoreSupportPatch( execute { fun transformStringReferences(transform: (str: String) -> String?) = classes.forEach { val mutableClass by lazy { - proxy(it).mutableClass + mutableClassBy(it) } it.methods.forEach classLoop@{ method -> @@ -88,12 +88,12 @@ fun gmsCoreSupportPatch( mutableClass.methods.first { MethodUtil.methodSignaturesMatch(it, method) } } - implementation.instructions.forEachIndexed insnLoop@{ index, instruction -> + implementation.instructions.forEachIndexed { index, instruction -> val string = ((instruction as? Instruction21c)?.reference as? StringReference)?.string - ?: return@insnLoop + ?: return@forEachIndexed // Apply transformation. - val transformedString = transform(string) ?: return@insnLoop + val transformedString = transform(string) ?: return@forEachIndexed mutableMethod.replaceInstruction( index, @@ -211,9 +211,7 @@ fun gmsCoreSupportPatch( } // Change the vendor of GmsCore in the extension. - gmsCoreSupportFingerprint.classDef.methods - .single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME } - .replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"") + gmsCoreSupportFingerprint.method.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"") executeBlock() } @@ -489,34 +487,6 @@ private object Constants { ) } -/** - * Abstract resource patch that allows Google apps to run without root and under a different package name - * by using GmsCore instead of Google Play Services. - * - * @param fromPackageName The package name of the original app. - * @param toPackageName The package name to fall back to if no custom package name is specified in patch options. - * @param spoofedPackageSignature The signature of the package to spoof to. - * @param gmsCoreVendorGroupIdOption The option to get the vendor group ID of GmsCore. - * @param executeBlock The additional execution block of the patch. - * @param block The additional block to build the patch. - */ -fun gmsCoreSupportResourcePatch( // This is here only for binary compatibility. - fromPackageName: String, - toPackageName: String, - spoofedPackageSignature: String, - gmsCoreVendorGroupIdOption: Option, - executeBlock: ResourcePatchContext.() -> Unit = {}, - block: ResourcePatchBuilder.() -> Unit = {}, -) = gmsCoreSupportResourcePatch( - fromPackageName, - toPackageName, - spoofedPackageSignature, - gmsCoreVendorGroupIdOption, - true, - executeBlock, - block -) - /** * Abstract resource patch that allows Google apps to run without root and under a different package name * by using GmsCore instead of Google Play Services. @@ -529,8 +499,7 @@ fun gmsCoreSupportResourcePatch( // This is here only for binary compatibility. * @param executeBlock The additional execution block of the patch. * @param block The additional block to build the patch. */ -// TODO: On the next major release make this public and delete the public overloaded constructor. -internal fun gmsCoreSupportResourcePatch( +fun gmsCoreSupportResourcePatch( fromPackageName: String, toPackageName: String, spoofedPackageSignature: String, diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/mapping/ResourceMappingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/mapping/ResourceMappingPatch.kt index 8a9e499ddb..bc380358dc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/mapping/ResourceMappingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/mapping/ResourceMappingPatch.kt @@ -1,64 +1,72 @@ package app.revanced.patches.shared.misc.mapping +import app.revanced.patcher.InstructionFilter.Companion.METHOD_MAX_INSTRUCTIONS +import app.revanced.patcher.LiteralFilter +import app.revanced.patcher.literal import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.resourcePatch import org.w3c.dom.Element -import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit +import java.util.Collections -// TODO: Probably renaming the patch/this is a good idea. -lateinit var resourceMappings: List - private set +data class ResourceElement(val type: String, val name: String, val id: Long) -val resourceMappingPatch = resourcePatch { - val resourceMappings = Collections.synchronizedList(mutableListOf()) - - execute { - val threadCount = Runtime.getRuntime().availableProcessors() - val threadPoolExecutor = Executors.newFixedThreadPool(threadCount) +private lateinit var resourceMappings: MutableMap - // Save the file in memory to concurrently read from it. - val resourceXmlFile = get("res/values/public.xml").readBytes() - - for (threadIndex in 0 until threadCount) { - threadPoolExecutor.execute thread@{ - document(resourceXmlFile.inputStream()).use { document -> +private fun setResourceId(type: String, name: String, id: Long) { + resourceMappings[type + name] = ResourceElement(type, name, id) +} - val resources = document.documentElement.childNodes - val resourcesLength = resources.length - val jobSize = resourcesLength / threadCount +/** + * @return A resource id of the given resource type and name. + * @throws PatchException if the resource is not found. + */ +fun getResourceId(type: String, name: String) = resourceMappings[type + name]?.id + ?: throw PatchException("Could not find resource type: $type name: $name") + +/** + * @return All resource elements. If a single resource id is needed instead use [getResourceId]. + */ +fun getResourceElements() = Collections.unmodifiableCollection(resourceMappings.values) + +/** + * @return If the resource exists. + */ +fun hasResourceId(type: String, name: String) = resourceMappings[type + name] != null + +/** + * Identical to [LiteralFilter] except uses a decoded resource literal value. + * + * Any patch with fingerprints of this filter must + * also declare [resourceMappingPatch] as a dependency. + */ +fun resourceLiteral( + type: String, + name: String, + maxBefore: Int = METHOD_MAX_INSTRUCTIONS, +) = literal({ getResourceId(type, name) }, null, maxBefore) - val batchStart = jobSize * threadIndex - val batchEnd = jobSize * (threadIndex + 1) - element@ for (i in batchStart until batchEnd) { - // Prevent out of bounds. - if (i >= resourcesLength) return@thread - val node = resources.item(i) - if (node !is Element) continue +val resourceMappingPatch = resourcePatch { + execute { + // Use a stream of the file, since no modifications are done + // and using a File parameter causes the file to be re-wrote when closed. + document(get("res/values/public.xml").inputStream()).use { document -> + val resources = document.documentElement.childNodes + val resourcesLength = resources.length + resourceMappings = HashMap(2 * resourcesLength) - val nameAttribute = node.getAttribute("name") - val typeAttribute = node.getAttribute("type") + for (i in 0 until resourcesLength) { + val node = resources.item(i) as? Element ?: continue + if (node.nodeName != "public") continue - if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) continue + val nameAttribute = node.getAttribute("name") + if (nameAttribute.startsWith("APKTOOL")) continue - val id = node.getAttribute("id").substring(2).toLong(16) + val typeAttribute = node.getAttribute("type") + val id = node.getAttribute("id").substring(2).toLong(16) - resourceMappings.add(ResourceElement(typeAttribute, nameAttribute, id)) - } - } + setResourceId(typeAttribute, nameAttribute, id) } } - - threadPoolExecutor.also { it.shutdown() }.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS) - - app.revanced.patches.shared.misc.mapping.resourceMappings = resourceMappings } } - -operator fun List.get(type: String, name: String) = resourceMappings.firstOrNull { - it.type == type && it.name == name -}?.id ?: throw PatchException("Could not find resource type: $type name: $name") - -data class ResourceElement internal constructor(val type: String, val name: String, val id: Long) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt index 344fd02dab..509c99336c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt @@ -2,14 +2,14 @@ package app.revanced.patches.shared.misc.pairip.license import app.revanced.patcher.fingerprint -internal val processLicenseResponseFingerprint = fingerprint { +internal val processLicenseResponseFingerprint by fingerprint { custom { method, classDef -> classDef.type == "Lcom/pairip/licensecheck/LicenseClient;" && method.name == "processResponse" } } -internal val validateLicenseResponseFingerprint = fingerprint { +internal val validateLicenseResponseFingerprint by fingerprint { custom { method, classDef -> classDef.type == "Lcom/pairip/licensecheck/ResponseValidator;" && method.name == "validateResponse" diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/Fingerprints.kt index cad00d8dea..9d0fbb5d14 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import app.revanced.patches.shared.misc.extension.EXTENSION_CLASS_DESCRIPTOR import com.android.tools.smali.dexlib2.AccessFlags -internal val themeLightColorResourceNameFingerprint = fingerprint { +internal val themeLightColorResourceNameFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Ljava/lang/String;") parameters() @@ -13,7 +13,7 @@ internal val themeLightColorResourceNameFingerprint = fingerprint { } } -internal val themeDarkColorResourceNameFingerprint = fingerprint { +internal val themeDarkColorResourceNameFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Ljava/lang/String;") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt index 828b20c129..8da55cfdbd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/SettingsPatch.kt @@ -7,7 +7,6 @@ import app.revanced.patches.all.misc.resources.addResource import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.BasePreference -import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference import app.revanced.util.ResourceGroup @@ -17,13 +16,6 @@ import app.revanced.util.insertFirst import app.revanced.util.returnEarly import org.w3c.dom.Node -// TODO: Delete this on next major version bump. -@Deprecated("Use non deprecated settings patch function") -fun settingsPatch ( - rootPreference: Pair, - preferences: Set, -) = settingsPatch(listOf(rootPreference), preferences) - private var themeForegroundColor : String? = null private var themeBackgroundColor : String? = null @@ -131,8 +123,7 @@ fun settingsPatch ( if (preference is PreferenceCategory) { removeIconsAndLayout(preference.preferences) - } - if (preference is PreferenceScreenPreference) { + } else if (preference is PreferenceScreenPreference) { removeIconsAndLayout(preference.preferences) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt index 2e26189b2f..43de07ec20 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/settings/preference/ListPreference.kt @@ -9,7 +9,6 @@ import org.w3c.dom.Document * * @param key The preference key. If null, other parameters must be specified. * @param titleKey The preference title key. - * @param summaryKey The preference summary key. * @param icon The preference icon resource name. * @param layout Layout declaration. * @param tag The preference class type. @@ -20,15 +19,12 @@ import org.w3c.dom.Document class ListPreference( key: String? = null, titleKey: String = "${key}_title", - /** Summary key is ignored and will be removed soon */ - //@Deprecated - summaryKey: String? = null, icon: String? = null, layout: String? = null, tag: String = "app.revanced.extension.shared.settings.preference.CustomDialogListPreference", val entriesKey: String? = "${key}_entries", val entryValuesKey: String? = "${key}_entry_values" -) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) { +) : BasePreference(key, titleKey, null, icon, layout, tag) { var entries: ArrayResource? = null private set var entryValues: ArrayResource? = null diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt index e6169bacb8..e7efdc41c8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt @@ -1,11 +1,13 @@ package app.revanced.patches.shared.misc.spoof import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val buildInitPlaybackRequestFingerprint = fingerprint { +internal val buildInitPlaybackRequestFingerprint by fingerprint { returns("Lorg/chromium/net/UrlRequest\$Builder;") opcodes( Opcode.MOVE_RESULT_OBJECT, @@ -17,7 +19,7 @@ internal val buildInitPlaybackRequestFingerprint = fingerprint { ) } -internal val buildPlayerRequestURIFingerprint = fingerprint { +internal val buildPlayerRequestURIFingerprint by fingerprint { returns("Ljava/lang/String;") opcodes( Opcode.INVOKE_VIRTUAL, // Register holds player request URI. @@ -33,9 +35,12 @@ internal val buildPlayerRequestURIFingerprint = fingerprint { ) } -internal val buildRequestFingerprint = fingerprint { +internal val buildRequestFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Lorg/chromium/net/UrlRequest;") + returns("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder; + instructions( + methodCall(name = "newUrlRequestBuilder") + ) custom { methodDef, _ -> // Different targets have slightly different parameters @@ -58,13 +63,22 @@ internal val buildRequestFingerprint = fingerprint { // Lorg/chromium/net/UrlRequest\$Callback; // L + // 20.16+ uses a refactored and extracted method: + // L + // Ljava/util/Map; + // [B + // L + // Lorg/chromium/net/UrlRequest$Callback; + // L + val parameterTypes = methodDef.parameterTypes - (parameterTypes.size == 7 || parameterTypes.size == 8) && + val parameterTypesSize = parameterTypes.size + (parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) && parameterTypes[1] == "Ljava/util/Map;" // URL headers. } } -internal val protobufClassParseByteBufferFingerprint = fingerprint { +internal val protobufClassParseByteBufferFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.STATIC) returns("L") parameters("L", "Ljava/nio/ByteBuffer;") @@ -77,9 +91,8 @@ internal val protobufClassParseByteBufferFingerprint = fingerprint { custom { method, _ -> method.name == "parseFrom" } } -internal val createStreamingDataFingerprint = fingerprint { +internal val createStreamingDataFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters("L") opcodes( Opcode.IPUT_OBJECT, @@ -95,9 +108,8 @@ internal val createStreamingDataFingerprint = fingerprint { } } -internal val buildMediaDataSourceFingerprint = fingerprint { +internal val buildMediaDataSourceFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters( "Landroid/net/Uri;", "J", @@ -112,29 +124,29 @@ internal val buildMediaDataSourceFingerprint = fingerprint { ) } -internal const val HLS_CURRENT_TIME_FEATURE_FLAG = 45355374L - -internal val hlsCurrentTimeFingerprint = fingerprint { +internal val hlsCurrentTimeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Z", "L") - literal { - HLS_CURRENT_TIME_FEATURE_FLAG - } + instructions( + literal(45355374L) // HLS current time feature flag. + ) } -internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint { +internal val nerdsStatsVideoFormatBuilderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Ljava/lang/String;") parameters("L") - strings("codecs=\"") + instructions( + string("codecs=\"") + ) } -internal val patchIncludedExtensionMethodFingerprint = fingerprint { +internal val patchIncludedExtensionMethodFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Z") parameters() custom { method, classDef -> - classDef.type == EXTENSION_CLASS_DESCRIPTOR && method.name == "isPatchIncluded" + method.name == "isPatchIncluded" && classDef.type == EXTENSION_CLASS_DESCRIPTOR } } @@ -142,28 +154,28 @@ internal val patchIncludedExtensionMethodFingerprint = fingerprint { // This code appears to replace the player config after the streams are loaded. // Flag is present in YouTube 19.34, but is missing Platypus stream replacement code until 19.43. // Flag and Platypus code is also present in newer versions of YouTube Music. -internal const val MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG = 45645570L - -internal val mediaFetchHotConfigFingerprint = fingerprint { - literal { MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG } +internal val mediaFetchHotConfigFingerprint by fingerprint { + instructions( + literal(45645570L) + ) } // 20.10+ -internal const val MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG = 45683169L - -internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint { - literal { MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG } +internal val mediaFetchHotConfigAlternativeFingerprint by fingerprint { + instructions( + literal(45683169L) + ) } // Feature flag that enables different code for parsing and starting video playback, // but it's exact purpose is not known. If this flag is enabled while stream spoofing // then videos will never start playback and load forever. // Flag does not seem to affect playback if spoofing is off. -internal const val PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG = 45665455L - -internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint { +internal val playbackStartDescriptorFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() returns("Z") - literal { PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG } + instructions( + literal(45665455L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt index 78deda394f..2789c105d0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt @@ -23,7 +23,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter @@ -53,57 +52,59 @@ fun spoofVideoStreamsPatch( // region Block /initplayback requests to fall back to /get_watch requests. - val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex - buildInitPlaybackRequestFingerprint.method.apply { - val targetRegister = getInstruction(moveUriStringIndex).registerA + buildInitPlaybackRequestFingerprint.let { + it.method.apply { + val moveUriStringIndex = it.instructionMatches.first().index + val targetRegister = getInstruction(moveUriStringIndex).registerA - addInstructions( - moveUriStringIndex + 1, - """ - invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$targetRegister - """, - ) + addInstructions( + moveUriStringIndex + 1, + """ + invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$targetRegister + """ + ) + } } // endregion // region Block /get_watch requests to fall back to /player requests. - val invokeToStringIndex = buildPlayerRequestURIFingerprint.patternMatch!!.startIndex + buildPlayerRequestURIFingerprint.let { + it.method.apply { + val invokeToStringIndex = it.instructionMatches.first().index + val uriRegister = getInstruction(invokeToStringIndex).registerC - buildPlayerRequestURIFingerprint.method.apply { - val uriRegister = getInstruction(invokeToStringIndex).registerC - - addInstructions( - invokeToStringIndex, - """ - invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; - move-result-object v$uriRegister - """, - ) + addInstructions( + invokeToStringIndex, + """ + invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; + move-result-object v$uriRegister + """ + ) + } } // endregion // region Get replacement streams at player requests. - buildRequestFingerprint.method.apply { - val newRequestBuilderIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "newUrlRequestBuilder" - } - val urlRegister = getInstruction(newRequestBuilderIndex).registerD - val freeRegister = findFreeRegister(newRequestBuilderIndex, urlRegister) + buildRequestFingerprint.let { + it.method.apply { + val builderIndex = it.instructionMatches.first().index + val urlRegister = getInstruction(builderIndex).registerD + val freeRegister = findFreeRegister(builderIndex, urlRegister) - addInstructions( - newRequestBuilderIndex, - """ - move-object v$freeRegister, p1 - invoke-static { v$urlRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V - """ - ) + addInstructions( + builderIndex, + """ + move-object v$freeRegister, p1 + invoke-static { v$urlRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V + """ + ) + } } // endregion @@ -113,7 +114,7 @@ fun spoofVideoStreamsPatch( createStreamingDataFingerprint.method.apply { val setStreamDataMethodName = "patch_setStreamingData" val resultMethodType = createStreamingDataFingerprint.classDef.type - val videoDetailsIndex = createStreamingDataFingerprint.patternMatch!!.endIndex + val videoDetailsIndex = createStreamingDataFingerprint.instructionMatches.last().index val videoDetailsRegister = getInstruction(videoDetailsIndex).registerA val videoDetailsClass = getInstruction(videoDetailsIndex).getReference()!!.type @@ -124,7 +125,7 @@ fun spoofVideoStreamsPatch( ) val protobufClass = protobufClassParseByteBufferFingerprint.method.definingClass - val setStreamingDataIndex = createStreamingDataFingerprint.patternMatch!!.startIndex + val setStreamingDataIndex = createStreamingDataFingerprint.instructionMatches.first().index val playerProtoClass = getInstruction(setStreamingDataIndex + 1) .getReference()!!.definingClass @@ -235,34 +236,42 @@ fun spoofVideoStreamsPatch( // region Fix iOS livestream current time. - hlsCurrentTimeFingerprint.method.insertLiteralOverride( - HLS_CURRENT_TIME_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" - ) + hlsCurrentTimeFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" + ) + } // endregion // region turn off stream config replacement feature flag. if (fixMediaFetchHotConfigChanges()) { - mediaFetchHotConfigFingerprint.method.insertLiteralOverride( - MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" - ) + mediaFetchHotConfigFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" + ) + } } if (fixMediaFetchHotConfigAlternativeChanges()) { - mediaFetchHotConfigAlternativeFingerprint.method.insertLiteralOverride( - MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" - ) + mediaFetchHotConfigAlternativeFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" + ) + } } if (fixParsePlaybackResponseFeatureFlag()) { - playbackStartDescriptorFeatureFlagFingerprint.method.insertLiteralOverride( - PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z" - ) + playbackStartDescriptorFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z" + ) + } } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt index 0e81d7e592..3b03634434 100644 --- a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.solidexplorer2.functionality.filesize import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val onReadyFingerprint = fingerprint { +internal val onReadyFingerprint by fingerprint { opcodes( Opcode.CONST_WIDE_32, // Constant storing the 2MB limit Opcode.CMP_LONG, diff --git a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt index 7ef5093015..c75a12b119 100644 --- a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt @@ -14,7 +14,7 @@ val removeFileSizeLimitPatch = bytecodePatch( execute { onReadyFingerprint.method.apply { - val cmpIndex = onReadyFingerprint.patternMatch!!.startIndex + 1 + val cmpIndex = onReadyFingerprint.instructionMatches.first().index + 1 val cmpResultRegister = getInstruction(cmpIndex).registerA replaceInstruction(cmpIndex, "const/4 v$cmpResultRegister, 0x0") diff --git a/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt index c52174f2c5..48ef210a78 100644 --- a/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt @@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference // Located @ ub.i0.h#p (9.5.0) -internal val createTabsFingerprint = fingerprint { +internal val createTabsFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE) returns("Ljava/util/List;") custom { method, _ -> @@ -26,7 +26,7 @@ internal val createTabsFingerprint = fingerprint { } // Located @ com.sony.songpal.mdr.vim.activity.MdrRemoteBaseActivity.e#run (9.5.0) -internal val showNotificationFingerprint = fingerprint { +internal val showNotificationFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("V") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt index 28780ea578..f6f442306f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val interceptFingerprint = fingerprint { +internal val interceptFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("L") parameters("L") @@ -16,9 +16,8 @@ internal val interceptFingerprint = fingerprint { strings("SC-Mob-UserPlan", "Configuration") } -internal val userConsumerPlanConstructorFingerprint = fingerprint { +internal val userConsumerPlanConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters( "Ljava/lang/String;", "Z", diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt index 3e56ed7275..76104a4230 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt @@ -54,7 +54,7 @@ val hideAdsPatch = bytecodePatch( // Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch. - val conditionIndex = interceptFingerprint.patternMatch!!.endIndex + 1 + val conditionIndex = interceptFingerprint.instructionMatches.last().index + 1 interceptFingerprint.method.addInstruction( conditionIndex, "return-object p1", diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/analytics/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/analytics/Fingerprints.kt index 2954b4d99c..1b18832b71 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/analytics/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/analytics/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.soundcloud.analytics import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val createTrackingApiFingerprint = fingerprint { +internal val createTrackingApiFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("L") custom { methodDef, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/offlinesync/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/offlinesync/Fingerprints.kt index 688fe36044..fe2aab19a5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/offlinesync/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/offlinesync/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val downloadOperationsURLBuilderFingerprint = fingerprint { +internal val downloadOperationsURLBuilderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String") parameters("L", "L") @@ -15,7 +15,7 @@ internal val downloadOperationsURLBuilderFingerprint = fingerprint { ) } -internal val downloadOperationsHeaderVerificationFingerprint = fingerprint { +internal val downloadOperationsHeaderVerificationFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "L") diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/shared/Fingerprints.kt index 3a50ae407e..646bb929a7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/shared/Fingerprints.kt @@ -4,8 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val featureConstructorFingerprint = fingerprint { - returns("V") +internal val featureConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters("Ljava/lang/String;", "Z", "Ljava/util/List;") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt index 5d555b1879..5b157f9240 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt @@ -7,11 +7,11 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val navigationBarItemSetClassFingerprint = fingerprint { +internal val navigationBarItemSetClassFingerprint by fingerprint { strings("NavigationBarItemSet(") } -internal val navigationBarItemSetConstructorFingerprint = fingerprint { +internal val navigationBarItemSetConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) // Make sure the method checks whether navigation bar items are null before adding them. // If this is not true, then we cannot patch the method and potentially transform the parameters into null. @@ -23,6 +23,6 @@ internal val navigationBarItemSetConstructorFingerprint = fingerprint { } } -internal val oldNavigationBarAddItemFingerprint = fingerprint { +internal val oldNavigationBarAddItemFingerprint by fingerprint { strings("Bottom navigation tabs exceeds maximum of 5 tabs") } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt index eb3ab78391..5de56ca826 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt @@ -4,21 +4,21 @@ import app.revanced.patcher.fingerprint import app.revanced.util.containsLiteralInstruction import com.android.tools.smali.dexlib2.AccessFlags -internal val colorSpaceUtilsClassFingerprint = fingerprint { +internal val colorSpaceUtilsClassFingerprint by fingerprint { strings("The specified color must be encoded in an RGB color space.") // Partial string match. } -internal val convertArgbToRgbaFingerprint = fingerprint { +internal val convertArgbToRgbaFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC, AccessFlags.FINAL) returns("J") parameters("J") } -internal val parseLottieJsonFingerprint = fingerprint { +internal val parseLottieJsonFingerprint by fingerprint { strings("Unsupported matte type: ") } -internal val parseAnimatedColorFingerprint = fingerprint { +internal val parseAnimatedColorFingerprint by fingerprint { parameters("L", "F") returns("Ljava/lang/Object;") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt deleted file mode 100644 index 365235bee0..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.spotify.lite.ondemand - -import com.android.tools.smali.dexlib2.Opcode -import app.revanced.patcher.fingerprint - -internal val onDemandFingerprint = fingerprint(fuzzyPatternScanThreshold = 2) { - returns("L") - parameters() - opcodes( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IPUT, - Opcode.RETURN_OBJECT, - ) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt deleted file mode 100644 index a624b42fd5..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.spotify.lite.ondemand - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("Patch no longer works and will be deleted soon") -@Suppress("unused") -val onDemandPatch = bytecodePatch( - description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.", -) { - compatibleWith("com.spotify.lite") - - execute { - // Spoof a premium account - - onDemandFingerprint.method.addInstruction( - onDemandFingerprint.patternMatch!!.endIndex - 1, - "const/4 v0, 0x2", - ) - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt index a797763a07..b81a6bb9c8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt @@ -34,15 +34,15 @@ internal val productStateProtoGetMapFingerprint get() = fingerprint { } } -internal val buildQueryParametersFingerprint = fingerprint { +internal val buildQueryParametersFingerprint by fingerprint { strings("trackRows", "device_type:tablet") } -internal val contextMenuViewModelClassFingerprint = fingerprint { +internal val contextMenuViewModelClassFingerprint by fingerprint { strings("ContextMenuViewModel(header=") } -internal val contextMenuViewModelAddItemFingerprint = fingerprint { +internal val contextMenuViewModelAddItemFingerprint by fingerprint { parameters("L") returns("V") custom { method, _ -> @@ -52,11 +52,11 @@ internal val contextMenuViewModelAddItemFingerprint = fingerprint { } } -internal val getViewModelFingerprint = fingerprint { +internal val getViewModelFingerprint by fingerprint { custom { method, _ -> method.name == "getViewModel" } } -internal val contextFromJsonFingerprint = fingerprint { +internal val contextFromJsonFingerprint by fingerprint { opcodes( Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT_OBJECT, @@ -70,19 +70,19 @@ internal val contextFromJsonFingerprint = fingerprint { } } -internal val readPlayerOptionOverridesFingerprint = fingerprint { +internal val readPlayerOptionOverridesFingerprint by fingerprint { custom { method, classDef -> method.name == "readPlayerOptionOverrides" && classDef.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;") } } -internal val protobufListsFingerprint = fingerprint { +internal val protobufListsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) custom { method, _ -> method.name == "emptyProtobufList" } } -internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint { +internal val abstractProtobufListEnsureIsMutableFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() returns("V") @@ -93,11 +93,11 @@ internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint { } } -internal val homeSectionFingerprint = fingerprint { +internal val homeSectionFingerprint by fingerprint { custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") } } -internal val homeStructureGetSectionsFingerprint = fingerprint { +internal val homeStructureGetSectionsFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("homeapi/proto/HomeStructure;") && method.indexOfFirstInstruction { opcode == Opcode.IGET_OBJECT && getReference()?.name == "sections_" @@ -116,9 +116,9 @@ internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = } internal const val PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME = "FetchMessageRequest;" -internal val pendragonJsonFetchMessageRequestFingerprint = +internal val pendragonJsonFetchMessageRequestFingerprint by reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME) internal const val PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME = "FetchMessageListRequest;" -internal val pendragonProtoFetchMessageListRequestFingerprint = +internal val pendragonProtoFetchMessageListRequestFingerprint by reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt index df36152425..55f63c47d4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt @@ -6,14 +6,16 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET -import app.revanced.util.* +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.returnEarly import app.revanced.util.toPublicAccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -51,10 +53,12 @@ val unlockPremiumPatch = bytecodePatch( } // Make _value accessible so that it can be overridden in the extension. - accountAttributeFingerprint.classDef.publicizeField("value_") + val accountFingerprint by accountAttributeFingerprint + accountFingerprint.classDef.publicizeField("value_") // Override the attributes map in the getter method. - productStateProtoGetMapFingerprint.method.apply { + val productFingerprint by productStateProtoGetMapFingerprint + productFingerprint.method.apply { val getAttributesMapIndex = indexOfFirstInstructionOrThrow(Opcode.IGET_OBJECT) val attributesMapRegister = getInstruction(getAttributesMapIndex).registerA @@ -69,7 +73,7 @@ val unlockPremiumPatch = bytecodePatch( // Add the query parameter trackRows to show popular tracks in the artist page. buildQueryParametersFingerprint.method.apply { val addQueryParameterConditionIndex = indexOfFirstInstructionReversedOrThrow( - buildQueryParametersFingerprint.stringMatches!!.first().index, Opcode.IF_EQZ + buildQueryParametersFingerprint.stringMatches.first().index, Opcode.IF_EQZ ) removeInstruction(addQueryParameterConditionIndex) @@ -86,7 +90,7 @@ val unlockPremiumPatch = bytecodePatch( // Enable choosing a specific song/artist via Google Assistant. contextFromJsonFingerprint.method.apply { - val insertIndex = contextFromJsonFingerprint.patternMatch!!.startIndex + val insertIndex = contextFromJsonFingerprint.patternMatch.startIndex // Both the URI and URL need to be modified. val registerUrl = getInstruction(insertIndex).registerC val registerUri = getInstruction(insertIndex + 2).registerD @@ -125,9 +129,7 @@ val unlockPremiumPatch = bytecodePatch( // Hook the method which adds context menu items and return before adding if the item is a Premium ad. contextMenuViewModelAddItemFingerprint.match(contextMenuViewModelClassDef).method.apply { val contextMenuItemClassType = parameterTypes.first() - val contextMenuItemClassDef = classes.find { - it.type == contextMenuItemClassType - } ?: throw PatchException("Could not find context menu item class.") + val contextMenuItemClassDef = classBy(contextMenuItemClassType.toString()) // The class returned by ContextMenuItem->getViewModel, which represents the actual context menu item. val viewModelClassType = getViewModelFingerprint.match(contextMenuItemClassDef).originalMethod.returnType @@ -164,12 +166,12 @@ val unlockPremiumPatch = bytecodePatch( // Find the protobuf array list class using the definingClass which contains the empty list static value. val classType = getInstruction(emptyProtobufListGetIndex).getReference()!!.definingClass - classes.find { it.type == classType } ?: throw PatchException("Could not find protobuf array list class.") + classBy { it.type == classType } } - val abstractProtobufListClassDef = classes.find { + val abstractProtobufListClassDef = classBy { it.type == protobufArrayListClassDef.superclass - } ?: throw PatchException("Could not find abstract protobuf list class.") + } // Need to allow mutation of the list so the home ads sections can be removed. // Protobuf array list has an 'isMutable' boolean parameter that sets the mutability. diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt index 6153f4b607..a255802e26 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Hooks.kt @@ -3,4 +3,4 @@ package app.revanced.patches.spotify.misc.extension import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.patches.spotify.shared.mainActivityOnCreateFingerprint -internal val mainActivityOnCreateHook = extensionHook(fingerprint = mainActivityOnCreateFingerprint) +internal val mainActivityOnCreateHook = extensionHook { mainActivityOnCreateFingerprint } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt index 6b25bc6304..29faebeab1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.spotify.misc.fix import app.revanced.patcher.fingerprint +import app.revanced.patcher.string -internal val getPackageInfoFingerprint = fingerprint { - strings( - "Failed to get the application signatures" +internal val getPackageInfoFingerprint by fingerprint { + instructions( + string("Failed to get the application signatures") ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatch.kt index 58606777dd..e10356a1cc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatch.kt @@ -23,7 +23,7 @@ val spoofPackageInfoPatch = bytecodePatch( // region Spoof signature. val failedToGetSignaturesStringIndex = - getPackageInfoFingerprint.stringMatches!!.first().index + getPackageInfoFingerprint.instructionMatches.first().index val concatSignaturesIndex = indexOfFirstInstructionReversedOrThrow( failedToGetSignaturesStringIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt deleted file mode 100644 index d59969c6c6..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.patches.spotify.misc.fix - -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("Superseded by spoofPackageInfoPatch", ReplaceWith("spoofPackageInfoPatch")) -@Suppress("unused") -val spoofSignaturePatch = bytecodePatch( - description = "Spoofs the signature of the app fix various functions of the app.", -) { - dependsOn(spoofPackageInfoPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt index b9edaaeacf..8548ece446 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt @@ -1,13 +1,14 @@ package app.revanced.patches.spotify.misc.fix.login import app.revanced.patcher.fingerprint +import app.revanced.patcher.literal import app.revanced.util.literal -internal val katanaProxyLoginMethodHandlerClassFingerprint = fingerprint { +internal val katanaProxyLoginMethodHandlerClassFingerprint by fingerprint { strings("katana_proxy_auth") } -internal val katanaProxyLoginMethodTryAuthorizeFingerprint = fingerprint { +internal val katanaProxyLoginMethodTryAuthorizeFingerprint by fingerprint { strings("e2e") literal { 0 } } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt index 99ec038c20..f551f24fe0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt @@ -3,11 +3,13 @@ package app.revanced.patches.spotify.misc.lyrics 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.fingerprint import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.stringOption import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c @@ -92,7 +94,19 @@ val changeLyricsProviderPatch = bytecodePatch( //endregion // region Replace the call to the HTTP client builder method used exclusively for lyrics by the modified one. - getLyricsHttpClientFingerprint(httpClientBuilderMethod).method.apply { + + + val getLyricsHttpClientFingerprint by fingerprint { + returns(httpClientBuilderMethod.returnType) + parameters() + custom { method, _ -> + method.indexOfFirstInstruction { + getReference() == httpClientBuilderMethod + } >= 0 + } + } + + getLyricsHttpClientFingerprint.method.apply { val getLyricsHttpClientIndex = indexOfFirstInstructionOrThrow { getReference() == httpClientBuilderMethod } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/Fingerprints.kt index f55fc349f4..b0ca654162 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val httpClientBuilderFingerprint = fingerprint { +internal val httpClientBuilderFingerprint by fingerprint { strings("client == null", "scheduler == null") } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt index f8ce3a262a..26aa529d48 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val shareCopyUrlFingerprint = fingerprint { +internal val shareCopyUrlFingerprint by fingerprint { returns("Ljava/lang/Object;") parameters("Ljava/lang/Object;") strings("clipboard", "Spotify Link") @@ -14,7 +14,7 @@ internal val shareCopyUrlFingerprint = fingerprint { } } -internal val shareCopyUrlLegacyFingerprint = fingerprint { +internal val shareCopyUrlLegacyFingerprint by fingerprint { returns("Ljava/lang/Object;") parameters("Ljava/lang/Object;") strings("clipboard", "createNewSession failed") @@ -23,7 +23,7 @@ internal val shareCopyUrlLegacyFingerprint = fingerprint { } } -internal val formatAndroidShareSheetUrlFingerprint = fingerprint { +internal val formatAndroidShareSheetUrlFingerprint by fingerprint { returns("Ljava/lang/String;") parameters("L", "Ljava/lang/String;") opcodes( @@ -38,7 +38,7 @@ internal val formatAndroidShareSheetUrlFingerprint = fingerprint { } } -internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint { +internal val formatAndroidShareSheetUrlLegacyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Ljava/lang/String;") parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/Fingerprints.kt index 3566512e84..81bcb2412a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.spotify.misc.widgets import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val canBindAppWidgetPermissionFingerprint = fingerprint { +internal val canBindAppWidgetPermissionFingerprint by fingerprint { strings("android.permission.BIND_APPWIDGET") opcodes(Opcode.AND_INT_LIT8) } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt deleted file mode 100644 index ddc92bcc48..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/navbar/PremiumNavbarTabPatch.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.spotify.navbar - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.spotify.misc.unlockPremiumPatch - -@Deprecated("Superseded by unlockPremiumPatch", ReplaceWith("unlockPremiumPatch")) -@Suppress("unused") -val premiumNavbarTabPatch = bytecodePatch( - description = "Hides the premium tab from the navigation bar.", -) { - dependsOn(unlockPremiumPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt index b107fd267d..a0f976332f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt @@ -11,7 +11,7 @@ private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivit */ internal const val SPOTIFY_MAIN_ACTIVITY_LEGACY = "Lcom/spotify/music/MainActivity;" -internal val mainActivityOnCreateFingerprint = fingerprint { +internal val mainActivityOnCreateFingerprint by fingerprint { custom { method, classDef -> method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY || classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY) @@ -28,7 +28,8 @@ private var isLegacyAppTarget: Boolean? = null context(BytecodePatchContext) internal val IS_SPOTIFY_LEGACY_APP_TARGET get(): Boolean { if (isLegacyAppTarget == null) { - isLegacyAppTarget = mainActivityOnCreateHook.fingerprint.originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY + isLegacyAppTarget = mainActivityOnCreateHook.invoke() + .fingerprint.originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY } return isLegacyAppTarget!! } diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/subscription/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/strava/subscription/Fingerprints.kt index 0458f45d3e..58047cc4cf 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/subscription/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/subscription/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.strava.subscription import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val getSubscribedFingerprint = fingerprint { +internal val getSubscribedFingerprint by fingerprint { opcodes(Opcode.IGET_BOOLEAN) custom { method, classDef -> classDef.endsWith("/SubscriptionDetailResponse;") && method.name == "getSubscribed" diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt index e59660472d..d0e061b9c6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/subscription/UnlockSubscriptionPatch.kt @@ -12,7 +12,7 @@ val unlockSubscriptionPatch = bytecodePatch( execute { getSubscribedFingerprint.method.replaceInstruction( - getSubscribedFingerprint.patternMatch!!.startIndex, + getSubscribedFingerprint.instructionMatches.first().index, "const/4 v0, 0x1", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt index c91bb961a2..69fcc44d41 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt @@ -52,7 +52,7 @@ val disableSubscriptionSuggestionsPatch = bytecodePatch( }, ) - val getModulesIndex = getModulesFingerprint.patternMatch!!.startIndex + val getModulesIndex = getModulesFingerprint.instructionMatches.first().index with(originalMethod) { removeInstruction(getModulesIndex) addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt index 1204a36f21..134c108692 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.strava.upselling import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val getModulesFingerprint = fingerprint { +internal val getModulesFingerprint by fingerprint { opcodes(Opcode.IGET_OBJECT) custom { method, classDef -> classDef.endsWith("/GenericLayoutEntry;") && method.name == "getModules" diff --git a/patches/src/main/kotlin/app/revanced/patches/swissid/integritycheck/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/swissid/integritycheck/Fingerprints.kt index 0efa845fbe..6e55bd5f41 100644 --- a/patches/src/main/kotlin/app/revanced/patches/swissid/integritycheck/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/swissid/integritycheck/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.swissid.integritycheck import app.revanced.patcher.fingerprint -internal val checkIntegrityFingerprint = fingerprint { +internal val checkIntegrityFingerprint by fingerprint { returns("V") parameters("Lcom/swisssign/deviceintegrity/model/DeviceIntegrityResult;") strings("it", "result") diff --git a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt index 4bd688de49..e198d21b18 100644 --- a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt @@ -2,13 +2,13 @@ package app.revanced.patches.ticktick.misc.themeunlock import app.revanced.patcher.fingerprint -internal val checkLockedThemesFingerprint = fingerprint { +internal val checkLockedThemesFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("Theme;") && method.name == "isLockedTheme" } } -internal val setThemeFingerprint = fingerprint { +internal val setThemeFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("ThemePreviewActivity;") && method.name == "lambda\$updateUserBtn\$1" } diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/Fingerprints.kt index f85dd2d072..32cf50f13e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/Fingerprints.kt @@ -4,13 +4,13 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val feedApiServiceLIZFingerprint = fingerprint { +internal val feedApiServiceLIZFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/FeedApiService;") && method.name == "fetchFeedList" } } -internal val followFeedFingerprint = fingerprint { +internal val followFeedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Lcom/ss/android/ugc/aweme/follow/presenter/FollowFeedList;") strings("getFollowFeedList") diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/cleardisplay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/cleardisplay/Fingerprints.kt index eb28683743..43aab883c0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/cleardisplay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/cleardisplay/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.tiktok.interaction.cleardisplay import app.revanced.patcher.fingerprint -internal val onClearDisplayEventFingerprint = fingerprint { +internal val onClearDisplayEventFingerprint by fingerprint { custom { method, classDef -> // Internally the feature is called "Clear mode". classDef.endsWith("/ClearModePanelComponent;") && method.name == "onClearModeEvent" diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/Fingerprints.kt index 160b49c158..5ab0efbbb6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.interaction.downloads import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val aclCommonShareFingerprint = fingerprint { +internal val aclCommonShareFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("I") custom { method, classDef -> @@ -12,7 +12,7 @@ internal val aclCommonShareFingerprint = fingerprint { } } -internal val aclCommonShare2Fingerprint = fingerprint { +internal val aclCommonShare2Fingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("I") custom { method, classDef -> @@ -21,7 +21,7 @@ internal val aclCommonShare2Fingerprint = fingerprint { } } -internal val aclCommonShare3Fingerprint = fingerprint { +internal val aclCommonShare3Fingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("I") custom { method, classDef -> @@ -30,7 +30,7 @@ internal val aclCommonShare3Fingerprint = fingerprint { } } -internal val downloadUriFingerprint = fingerprint { +internal val downloadUriFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Landroid/net/Uri;") parameters( diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/Fingerprints.kt index ce372ea421..66fef7177f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/Fingerprints.kt @@ -2,10 +2,10 @@ package app.revanced.patches.tiktok.interaction.seekbar import app.revanced.patcher.fingerprint -internal val setSeekBarShowTypeFingerprint = fingerprint { +internal val setSeekBarShowTypeFingerprint by fingerprint { strings("seekbar show type change, change to:") } -internal val shouldShowSeekBarFingerprint = fingerprint { +internal val shouldShowSeekBarFingerprint by fingerprint { strings("can not show seekbar, state: 1, not in resume") } diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/Fingerprints.kt index 221036bb96..ab224a1cca 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/Fingerprints.kt @@ -3,13 +3,13 @@ package app.revanced.patches.tiktok.interaction.speed import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val getSpeedFingerprint = fingerprint { +internal val getSpeedFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/BaseListFragmentPanel;") && method.name == "onFeedSpeedSelectedEvent" } } -internal val setSpeedFingerprint = fingerprint { +internal val setSpeedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("V") parameters("Ljava/lang/String;", "Lcom/ss/android/ugc/aweme/feed/model/Aweme;", "F") diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/Fingerprints.kt index 929ef86729..439f63862b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/Fingerprints.kt @@ -2,14 +2,14 @@ package app.revanced.patches.tiktok.misc.login.disablerequirement import app.revanced.patcher.fingerprint -internal val mandatoryLoginServiceFingerprint = fingerprint { +internal val mandatoryLoginServiceFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/MandatoryLoginService;") && method.name == "enableForcedLogin" } } -internal val mandatoryLoginService2Fingerprint = fingerprint { +internal val mandatoryLoginService2Fingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/MandatoryLoginService;") && method.name == "shouldShowForcedLogin" diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/Fingerprints.kt index a40f5251f5..19d045db01 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.misc.login.fixgoogle import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val googleAuthAvailableFingerprint = fingerprint { +internal val googleAuthAvailableFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() @@ -12,7 +12,7 @@ internal val googleAuthAvailableFingerprint = fingerprint { } } -internal val googleOneTapAuthAvailableFingerprint = fingerprint { +internal val googleOneTapAuthAvailableFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/Fingerprints.kt index d1c4d6de68..4317948c41 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/Fingerprints.kt @@ -2,32 +2,32 @@ package app.revanced.patches.tiktok.misc.settings import app.revanced.patcher.fingerprint -internal val addSettingsEntryFingerprint = fingerprint { +internal val addSettingsEntryFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/SettingNewVersionFragment;") && method.name == "initUnitManger" } } -internal val adPersonalizationActivityOnCreateFingerprint = fingerprint { +internal val adPersonalizationActivityOnCreateFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/AdPersonalizationActivity;") && method.name == "onCreate" } } -internal val settingsEntryFingerprint = fingerprint { +internal val settingsEntryFingerprint by fingerprint { strings("pls pass item or extends the EventUnit") } -internal val settingsEntryInfoFingerprint = fingerprint { +internal val settingsEntryInfoFingerprint by fingerprint { strings( "ExposeItem(title=", ", icon=", ) } -internal val settingsStatusLoadFingerprint = fingerprint { +internal val settingsStatusLoadFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("Lapp/revanced/extension/tiktok/settings/SettingsStatus;") && method.name == "load" diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt index 40a45650de..b069b88f55 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/SpoofSimPatch.kt @@ -69,7 +69,7 @@ val spoofSimPatch = bytecodePatch( } } }.forEach { (classDef, methods) -> - with(proxy(classDef).mutableClass) { + with(mutableClassBy(classDef)) { methods.forEach { (method, patches) -> with(findMutableMethodOf(method)) { while (!patches.isEmpty()) { diff --git a/patches/src/main/kotlin/app/revanced/patches/tiktok/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tiktok/shared/Fingerprints.kt index 3e98d213e5..508d469645 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tiktok/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tiktok/shared/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val getEnterFromFingerprint = fingerprint { +internal val getEnterFromFingerprint by fingerprint { returns("Ljava/lang/String;") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Z") @@ -22,7 +22,7 @@ internal val getEnterFromFingerprint = fingerprint { } } -internal val onRenderFirstFrameFingerprint = fingerprint { +internal val onRenderFirstFrameFingerprint by fingerprint { strings("method_enable_viewpager_preload_duration") custom { _, classDef -> classDef.endsWith("/BaseListFragmentPanel;") diff --git a/patches/src/main/kotlin/app/revanced/patches/trakt/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/trakt/Fingerprints.kt index 4a02c62215..0d985d88c7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/trakt/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/trakt/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.trakt import app.revanced.patcher.fingerprint -internal val isVIPEPFingerprint = fingerprint { +internal val isVIPEPFingerprint by fingerprint { custom { method, classDef -> if (!classDef.endsWith("RemoteUser;")) return@custom false @@ -10,7 +10,7 @@ internal val isVIPEPFingerprint = fingerprint { } } -internal val isVIPFingerprint = fingerprint { +internal val isVIPFingerprint by fingerprint { custom { method, classDef -> if (!classDef.endsWith("RemoteUser;")) return@custom false @@ -18,7 +18,7 @@ internal val isVIPFingerprint = fingerprint { } } -internal val remoteUserFingerprint = fingerprint { +internal val remoteUserFingerprint by fingerprint { custom { _, classDef -> classDef.endsWith("RemoteUser;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/Fingerprints.kt index 12ffa15c15..0cd634ee1b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tudortmund/lockscreen/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.tudortmund.lockscreen import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val brightnessFingerprint = fingerprint { +internal val brightnessFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC) returns("V") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/Fingerprints.kt index 67e051a7ba..525f5a5e74 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/Fingerprints.kt @@ -6,6 +6,6 @@ import app.revanced.patcher.fingerprint // It shows whenever you visit a certain blog for the second time and disables itself // if it was shown a total of 3 times (stored in app storage). // This targets the BlogNotifyCtaDialog.isEnabled() method to let it always return false. -internal val isBlogNotifyEnabledFingerprint = fingerprint { +internal val isBlogNotifyEnabledFingerprint by fingerprint { strings("isEnabled --> ", "blog_notify_enabled") } diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/Fingerprints.kt index 7d00f2f1bd..2be1a3cefb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint // This method is responsible for loading and displaying the visual Layout of the Gift Message Popup. -internal val showGiftMessagePopupFingerprint = fingerprint { +internal val showGiftMessagePopupFingerprint by fingerprint { accessFlags(AccessFlags.FINAL, AccessFlags.PUBLIC) returns("V") strings("activity", "anchorView", "textMessage") diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt index e24ca2884a..742a8fd4d2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt @@ -13,7 +13,7 @@ import app.revanced.patcher.fingerprint // Some features seem to be very old and never removed, though, such as Google Login. // The startIndex of the opcode pattern is at the start of the function after the arg null check. // we want to insert our instructions there. -internal val getFeatureValueFingerprint = fingerprint { +internal val getFeatureValueFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters("L", "Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt index c2da658aad..06f7d44379 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt @@ -69,7 +69,7 @@ val overrideFeatureFlagsPatch = bytecodePatch( // This is equivalent to // String forcedValue = getValueOverride(feature) // if (forcedValue != null) return forcedValue - val getFeatureIndex = getFeatureValueFingerprint.patternMatch!!.startIndex + val getFeatureIndex = getFeatureValueFingerprint.instructionMatches.first().index getFeatureValueFingerprint.method.addInstructionsWithLabels( getFeatureIndex, """ diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt index 11616fcc92..8d9f4cfd3d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.fingerprint // Fingerprint for the addQueryParam method from retrofit2 // https://github.com/square/retrofit/blob/trunk/retrofit/src/main/java/retrofit2/RequestBuilder.java#L186 // Injecting here allows modifying dynamically set query parameters -internal val addQueryParamFingerprint = fingerprint { +internal val addQueryParamFingerprint by fingerprint { parameters("Ljava/lang/String;", "Ljava/lang/String;", "Z") strings("Malformed URL. Base: ", ", Relative: ") } @@ -14,7 +14,7 @@ internal val addQueryParamFingerprint = fingerprint { // Fingerprint for the parseHttpMethodAndPath method from retrofit2 // https://github.com/square/retrofit/blob/ebf87b10997e2136af4d335276fa950221852c64/retrofit/src/main/java/retrofit2/RequestFactory.java#L270-L302 // Injecting here allows modifying the path/query params of API endpoints defined via annotations -internal val httpPathParserFingerprint = fingerprint { +internal val httpPathParserFingerprint by fingerprint { opcodes( Opcode.IPUT_OBJECT, Opcode.IPUT_BOOLEAN, diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt index dbe75d5f8b..ad9f52f4b0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt @@ -21,7 +21,7 @@ val fixOldVersionsPatch = bytecodePatch( // Remove the live query parameters from the path when it's specified via a @METHOD annotation. for (liveQueryParameter in liveQueryParameters) { httpPathParserFingerprint.method.addInstructions( - httpPathParserFingerprint.patternMatch!!.endIndex + 1, + httpPathParserFingerprint.instructionMatches.last().index + 1, """ # urlPath = urlPath.replace(liveQueryParameter, "") const-string p1, "$liveQueryParameter" diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt index c4ab799e85..5e8ad5c70a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt @@ -24,7 +24,7 @@ val filterTimelineObjectsPatch = bytecodePatch( dependsOn(sharedExtensionPatch) execute { - val filterInsertIndex = timelineFilterExtensionFingerprint.patternMatch!!.startIndex + val filterInsertIndex = timelineFilterExtensionFingerprint.instructionMatches.first().index timelineFilterExtensionFingerprint.method.apply { val addInstruction = getInstruction(filterInsertIndex + 1) @@ -47,7 +47,7 @@ val filterTimelineObjectsPatch = bytecodePatch( } } - mapOf( + arrayOf( timelineConstructorFingerprint to 1, postsResponseConstructorFingerprint to 2, ).forEach { (fingerprint, timelineObjectsRegister) -> diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt index b8ed3bfc4e..75be30004a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt @@ -6,7 +6,7 @@ import com.android.tools.smali.dexlib2.Opcode // This is the constructor of the PostsResponse class. // The same applies here as with the TimelineConstructorFingerprint. -internal val postsResponseConstructorFingerprint = fingerprint { +internal val postsResponseConstructorFingerprint by fingerprint { accessFlags(AccessFlags.CONSTRUCTOR, AccessFlags.PUBLIC) custom { method, classDef -> classDef.endsWith("/PostsResponse;") && method.parameters.size == 4 } } @@ -14,7 +14,7 @@ internal val postsResponseConstructorFingerprint = fingerprint { // This is the constructor of the Timeline class. // It receives the List as an argument with a @Json annotation, so this should be the first time // that the List is exposed in non-library code. -internal val timelineConstructorFingerprint = fingerprint { +internal val timelineConstructorFingerprint by fingerprint { strings("timelineObjectsList") custom { method, classDef -> classDef.endsWith("/Timeline;") && method.parameters[0].type == "Ljava/util/List;" @@ -24,7 +24,7 @@ internal val timelineConstructorFingerprint = fingerprint { // This fingerprints the extension TimelineFilterPatch.filterTimeline method. // The opcode fingerprint is searching for // if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove(); -internal val timelineFilterExtensionFingerprint = fingerprint { +internal val timelineFilterExtensionFingerprint by fingerprint { opcodes( Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY" Opcode.INVOKE_VIRTUAL, // HashSet.add(^) diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/audio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/audio/Fingerprints.kt index 21e9cb6d2a..3bae02166c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/audio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/audio/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitch.ad.audio import app.revanced.patcher.fingerprint -internal val audioAdsPresenterPlayFingerprint = fingerprint { +internal val audioAdsPresenterPlayFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("AudioAdsPlayerPresenter;") && method.name == "playAd" } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/Fingerprints.kt index 3e9853bd61..209f91d2b2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitch.ad.embedded import app.revanced.patcher.fingerprint -internal val createsUsherClientFingerprint = fingerprint { +internal val createsUsherClientFingerprint by fingerprint { custom { method, _ -> method.name == "buildOkHttpClient" && method.definingClass.endsWith("Ltv/twitch/android/network/OkHttpClientFactory;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AdPatch.kt index 48ecefba8e..2cf8e55925 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/shared/util/AdPatch.kt @@ -29,7 +29,7 @@ fun adPatch( classDefType: String, methodNames: Set, returnMethod: ReturnMethod, - ) = with(classBy { classDefType == it.type }?.mutableClass) { + ) = with(mutableClassByOrNull(classDefType)) { this ?: return false methods.filter { it.name in methodNames }.forEach { diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/video/Fingerprints.kt index d03449733f..4bd8abb2a0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/ad/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/ad/video/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitch.ad.video import app.revanced.patcher.fingerprint -internal val checkAdEligibilityLambdaFingerprint = fingerprint { +internal val checkAdEligibilityLambdaFingerprint by fingerprint { returns("Lio/reactivex/Single;") parameters("L") custom { method, _ -> @@ -11,7 +11,7 @@ internal val checkAdEligibilityLambdaFingerprint = fingerprint { } } -internal val contentConfigShowAdsFingerprint = fingerprint { +internal val contentConfigShowAdsFingerprint by fingerprint { returns("Z") parameters() custom { method, _ -> @@ -19,7 +19,7 @@ internal val contentConfigShowAdsFingerprint = fingerprint { } } -internal val getReadyToShowAdFingerprint = fingerprint { +internal val getReadyToShowAdFingerprint by fingerprint { returns("Ltv/twitch/android/core/mvp/presenter/StateAndAction;") parameters("L", "L") custom { method, _ -> diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/Fingerprints.kt index 21da99a5bb..04ef723432 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/Fingerprints.kt @@ -3,21 +3,20 @@ package app.revanced.patches.twitch.chat.antidelete import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val chatUtilCreateDeletedSpanFingerprint = fingerprint { +internal val chatUtilCreateDeletedSpanFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("ChatUtil\$Companion;") && method.name == "createDeletedSpanFromChatMessageSpan" } } -internal val deletedMessageClickableSpanCtorFingerprint = fingerprint { +internal val deletedMessageClickableSpanCtorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") custom { _, classDef -> classDef.endsWith("DeletedMessageClickableSpan;") } } -internal val setHasModAccessFingerprint = fingerprint { +internal val setHasModAccessFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("DeletedMessageClickableSpan;") && method.name == "setHasModAccess" } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/Fingerprints.kt index 80abc9ac41..59986152c0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitch.chat.autoclaim import app.revanced.patcher.fingerprint -internal val communityPointsButtonViewDelegateFingerprint = fingerprint { +internal val communityPointsButtonViewDelegateFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("CommunityPointsButtonViewDelegate;") && method.name == "showClaimAvailable" diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/debug/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/debug/Fingerprints.kt index 665180c19b..49a8601f26 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/debug/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/debug/Fingerprints.kt @@ -2,19 +2,19 @@ package app.revanced.patches.twitch.debug import app.revanced.patcher.fingerprint -internal val isDebugConfigEnabledFingerprint = fingerprint { +internal val isDebugConfigEnabledFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/BuildConfigUtil;") && method.name == "isDebugConfigEnabled" } } -internal val isOmVerificationEnabledFingerprint = fingerprint { +internal val isOmVerificationEnabledFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/BuildConfigUtil;") && method.name == "isOmVerificationEnabled" } } -internal val shouldShowDebugOptionsFingerprint = fingerprint { +internal val shouldShowDebugOptionsFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/BuildConfigUtil;") && method.name == "shouldShowDebugOptions" } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitch/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitch/misc/settings/Fingerprints.kt index 43d5bb39bf..f39c762e94 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitch/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitch/misc/settings/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.twitch.misc.settings import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val menuGroupsOnClickFingerprint = fingerprint { +internal val menuGroupsOnClickFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC, AccessFlags.FINAL) returns("V") parameters("L", "L", "L") @@ -13,21 +13,21 @@ internal val menuGroupsOnClickFingerprint = fingerprint { } } -internal val menuGroupsUpdatedFingerprint = fingerprint { +internal val menuGroupsUpdatedFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/SettingsMenuPresenter\$Event\$MenuGroupsUpdated;") && method.name == "" } } -internal val settingsActivityOnCreateFingerprint = fingerprint { +internal val settingsActivityOnCreateFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/SettingsActivity;") && method.name == "onCreate" } } -internal val settingsMenuItemEnumFingerprint = fingerprint { +internal val settingsMenuItemEnumFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("/SettingsMenuItem;") && method.name == "" } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt index dc100acb10..b01f75081f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val buildMediaOptionsSheetFingerprint = fingerprint { +internal val buildMediaOptionsSheetFingerprint by fingerprint { opcodes( Opcode.IF_EQ, Opcode.SGET_OBJECT, @@ -14,13 +14,12 @@ internal val buildMediaOptionsSheetFingerprint = fingerprint { strings("mediaEntity", "media_options_sheet") } -internal val constructMediaOptionsSheetFingerprint = fingerprint { +internal val constructMediaOptionsSheetFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") strings("captionsState") } -internal val showDownloadVideoUpsellBottomSheetFingerprint = fingerprint { +internal val showDownloadVideoUpsellBottomSheetFingerprint by fingerprint { returns("Z") strings("mediaEntity", "url") opcodes(Opcode.IF_EQZ) diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt index 6f2b9c12c7..945f0a47b9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt @@ -27,7 +27,7 @@ val unlockDownloadsPatch = bytecodePatch( // Allow downloads for non-premium users. showDownloadVideoUpsellBottomSheetFingerprint.patch { - val checkIndex = patternMatch!!.startIndex + val checkIndex = instructionMatches.first().index val register = method.getInstruction(checkIndex).registerA checkIndex to register @@ -42,25 +42,26 @@ val unlockDownloadsPatch = bytecodePatch( } // Make GIFs downloadable. - val patternMatch = buildMediaOptionsSheetFingerprint.patternMatch!! - buildMediaOptionsSheetFingerprint.method.apply { - val checkMediaTypeIndex = patternMatch.startIndex - val checkMediaTypeInstruction = getInstruction(checkMediaTypeIndex) + buildMediaOptionsSheetFingerprint.let { + it.method.apply { + val checkMediaTypeIndex = it.instructionMatches.first().index + val checkMediaTypeInstruction = getInstruction(checkMediaTypeIndex) - // Treat GIFs as videos. - addInstructionsWithLabels( - checkMediaTypeIndex + 1, - """ + // Treat GIFs as videos. + addInstructionsWithLabels( + checkMediaTypeIndex + 1, + """ const/4 v${checkMediaTypeInstruction.registerB}, 0x2 # GIF if-eq v${checkMediaTypeInstruction.registerA}, v${checkMediaTypeInstruction.registerB}, :video """, - ExternalLabel("video", getInstruction(patternMatch.endIndex)), - ) + ExternalLabel("video", getInstruction(it.instructionMatches.last().index)), + ) - // Remove media.isDownloadable check. - removeInstruction( - instructions.first { it.opcode == Opcode.IGET_BOOLEAN }.location.index + 1, - ) + // Remove media.isDownloadable check. + removeInstruction( + instructions.first { it.opcode == Opcode.IGET_BOOLEAN }.location.index + 1, + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/layout/viewcount/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/layout/viewcount/Fingerprints.kt index 625b6f0bb7..199ef49c2a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/layout/viewcount/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/layout/viewcount/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitter.layout.viewcount import app.revanced.patcher.fingerprint -internal val viewCountsEnabledFingerprint = fingerprint { +internal val viewCountsEnabledFingerprint by fingerprint { returns("Z") strings("view_counts_public_visibility_enabled") } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt index 9d813b7ad9..97347a8ee9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/DynamicColorPatch.kt @@ -39,8 +39,7 @@ val dynamicColorPatch = resourcePatch( } document("res/values-v31/colors.xml").use { document -> - - mapOf( + arrayOf( "ps__twitter_blue" to "@color/twitter_blue", "ps__twitter_blue_pressed" to "@color/twitter_blue_fill_pressed", "twitter_blue" to "@android:color/system_accent1_400", @@ -60,7 +59,7 @@ val dynamicColorPatch = resourcePatch( } document("res/values-night-v31/colors.xml").use { document -> - mapOf( + arrayOf( "twitter_blue" to "@android:color/system_accent1_200", "twitter_blue_fill_pressed" to "@android:color/system_accent1_300", "twitter_blue_opacity_30" to "@android:color/system_accent1_50", diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt index 337aeb5670..1158df15d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.twitter.misc.hook.json import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.Opcode -internal val jsonHookPatchFingerprint = fingerprint { +internal val jsonHookPatchFingerprint by fingerprint { opcodes( Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list. // Add hooks to the hooks list. @@ -12,7 +12,7 @@ internal val jsonHookPatchFingerprint = fingerprint { custom { method, _ -> method.name == "" } } -internal val jsonInputStreamFingerprint = fingerprint { +internal val jsonInputStreamFingerprint by fingerprint { custom { method, _ -> if (method.parameterTypes.isEmpty()) { false @@ -22,6 +22,6 @@ internal val jsonInputStreamFingerprint = fingerprint { } } -internal val loganSquareFingerprint = fingerprint { +internal val loganSquareFingerprint by fingerprint { custom { _, classDef -> classDef.endsWith("LoganSquare;") } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt index 56785cae4c..d3e95102fa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt @@ -22,7 +22,7 @@ fun addJsonHook( jsonHookPatchFingerprint.method.apply { // Insert hooks right before calling buildList. - val insertIndex = jsonHookPatchFingerprint.patternMatch!!.endIndex + val insertIndex = jsonHookPatchFingerprint.instructionMatches.last().index addInstructions( insertIndex, @@ -48,11 +48,9 @@ val jsonHookPatch = bytecodePatch( execute { jsonHookPatchFingerprint.apply { - // Make sure the extension is present. - val jsonHookPatch = classBy { classDef -> classDef.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR } - ?: throw PatchException("Could not find the extension.") + val jsonHookPatch = classBy(JSON_HOOK_PATCH_CLASS_DESCRIPTOR) - matchOrNull(jsonHookPatch.immutableClass) + matchOrNull(jsonHookPatch) ?: throw PatchException("Unexpected extension.") } @@ -61,7 +59,7 @@ val jsonHookPatch = bytecodePatch( .fields .firstOrNull { it.name == "JSON_FACTORY" } ?.type - .let { type -> classes.find { it.type == type } } + ?.let { type -> classes.classBy(type) } ?: throw PatchException("Could not find required class.") // Hook the methods first parameter. @@ -77,7 +75,7 @@ val jsonHookPatch = bytecodePatch( finalize { // Remove hooks.add(dummyHook). jsonHookPatchFingerprint.method.apply { - val addDummyHookIndex = jsonHookPatchFingerprint.patternMatch!!.endIndex - 2 + val addDummyHookIndex = jsonHookPatchFingerprint.instructionMatches.last().index - 2 removeInstructions(addDummyHookIndex, 2) } @@ -99,8 +97,8 @@ class JsonHook( internal var added = false init { - classBy { it.type == descriptor }?.let { - it.mutableClass.also { classDef -> + mutableClassBy(descriptor).let { + it.also { classDef -> if ( classDef.superclass != JSON_HOOK_CLASS_DESCRIPTOR || !classDef.fields.any { field -> field.name == "INSTANCE" } @@ -108,6 +106,6 @@ class JsonHook( throw InvalidClassException(classDef.type, "Not a hook class") } } - } ?: throw ClassNotFoundException("Failed to find hook class $descriptor") + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index bf3d9afd23..ab0a8418d8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -6,9 +6,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.stringOption -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.twitter.misc.extension.sharedExtensionPatch import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -21,7 +20,7 @@ internal val changeLinkSharingDomainResourcePatch = resourcePatch { dependsOn(resourceMappingPatch) execute { - tweetShareLinkTemplateId = resourceMappings["string", "tweet_share_link"] + tweetShareLinkTemplateId = getResourceId("string", "tweet_share_link") } } @@ -55,7 +54,7 @@ val changeLinkSharingDomainPatch = bytecodePatch( execute { val replacementIndex = - linkSharingDomainFingerprint.stringMatches!!.first().index + linkSharingDomainFingerprint.stringMatches.first().index val domainRegister = linkSharingDomainFingerprint.method.getInstruction(replacementIndex).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt index 0d5d0e6f80..abbf40e890 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt @@ -4,28 +4,28 @@ import app.revanced.patcher.fingerprint import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags -internal val openLinkFingerprint = fingerprint { +internal val openLinkFingerprint by fingerprint { returns("V") parameters("Landroid/content/Context;", "Landroid/content/Intent;", "Landroid/os/Bundle;") } -internal val sanitizeSharingLinksFingerprint = fingerprint { +internal val sanitizeSharingLinksFingerprint by fingerprint { returns("Ljava/lang/String;") strings("", "shareParam", "sessionToken") } // Returns a shareable link string based on a tweet ID and a username. -internal val linkBuilderFingerprint = fingerprint { +internal val linkBuilderFingerprint by fingerprint { strings("/%1\$s/status/%2\$d") } // Gets Resource string for share link view available by pressing "Share via" button. -internal val linkResourceGetterFingerprint = fingerprint { +internal val linkResourceGetterFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Landroid/content/res/Resources;") literal { tweetShareLinkTemplateId } } -internal val linkSharingDomainFingerprint = fingerprint { +internal val linkSharingDomainFingerprint by fingerprint { strings("https://fxtwitter.com") } diff --git a/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/Fingerprints.kt deleted file mode 100644 index 0809324c7f..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/Fingerprints.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.patches.vsco.misc.pro - -import app.revanced.patcher.fingerprint - -internal val revCatSubscriptionFingerprint = fingerprint { - returns("V") - strings("use_debug_subscription_settings") - custom { _, classDef -> - classDef.endsWith("/RevCatSubscriptionSettingsRepository;") - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt b/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt deleted file mode 100644 index be0278dd9e..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/vsco/misc/pro/UnlockProPatch.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.vsco.misc.pro - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("This patch is deprecated because it does not work anymore and will be removed in the future.") -@Suppress("unused") -val unlockProPatch = bytecodePatch( - description = "Unlocks pro features.", -) { - compatibleWith("com.vsco.cam"("345")) - - execute { - // Set isSubscribed to true. - revCatSubscriptionFingerprint.method.addInstruction(0, "const p1, 0x1") - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/Fingerprints.kt index 6eb7bd176b..03ff60e0c0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.warnwetter.misc.firebasegetcert import app.revanced.patcher.fingerprint -internal val getMessagingCertFingerprint = fingerprint { +internal val getMessagingCertFingerprint by fingerprint { returns("Ljava/lang/String;") strings( "ContentValues", @@ -11,7 +11,7 @@ internal val getMessagingCertFingerprint = fingerprint { ) } -internal val getRegistrationCertFingerprint = fingerprint { +internal val getRegistrationCertFingerprint by fingerprint { returns("Ljava/lang/String;") strings( "FirebaseRemoteConfig", diff --git a/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/Fingerprints.kt index d33880de70..0249856381 100644 --- a/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/Fingerprints.kt @@ -2,7 +2,7 @@ package app.revanced.patches.warnwetter.misc.promocode import app.revanced.patcher.fingerprint -internal val promoCodeUnlockFingerprint = fingerprint { +internal val promoCodeUnlockFingerprint by fingerprint { custom { method, classDef -> classDef.endsWith("PromoTokenVerification;") && method.name == "isValid" } diff --git a/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/Fingerprints.kt index e326c26825..19fdb02d85 100644 --- a/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.willhaben.ads import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val adResolverFingerprint = fingerprint { +internal val adResolverFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("L", "L") @@ -15,7 +15,7 @@ internal val adResolverFingerprint = fingerprint { ) } -internal val whAdViewInjectorFingerprint = fingerprint { +internal val whAdViewInjectorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "L", "L", "Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/Fingerprints.kt deleted file mode 100644 index f199f127c7..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/Fingerprints.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.windyapp.misc.unlockpro - -import app.revanced.patcher.fingerprint - -internal val checkProFingerprint = fingerprint { - returns("I") - custom { method, classDef -> - classDef.endsWith("RawUserData;") && method.name == "isPro" - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt b/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt deleted file mode 100644 index c0323c72ed..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.windyapp.misc.unlockpro - -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("This patch no longer works and will be removed in the future.") -@Suppress("unused") -val unlockProPatch = bytecodePatch( - description = "Unlocks all pro features.", -) { - compatibleWith("co.windyapp.android") - - execute { - checkProFingerprint.method.addInstructions( - 0, - """ - const/16 v0, 0x1 - return v0 - """, - ) - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/Fingerprints.kt index 254b440f39..8091108cfc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/Fingerprints.kt @@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val fullScreenEngagementAdContainerFingerprint = fingerprint { +internal val fullScreenEngagementAdContainerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt index 5c3874ab99..b9d4ce0e7f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt @@ -7,9 +7,8 @@ import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.fix.verticalscroll.verticalScrollPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.ad.getpremium.hideGetPremiumPatch import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fixBackToExitGesturePatch @@ -58,8 +57,8 @@ private val hideAdsResourcePatch = resourcePatch { addLithoFilter("Lapp/revanced/extension/youtube/patches/components/AdsFilter;") - adAttributionId = resourceMappings["id", "ad_attribution"] - fullScreenEngagementAdContainer = resourceMappings["id", "fullscreen_engagement_ad_container"] + adAttributionId = getResourceId("id", "ad_attribution") + fullScreenEngagementAdContainer = getResourceId("id", "fullscreen_engagement_ad_container") } } @@ -125,8 +124,7 @@ val hideAdsPatch = bytecodePatch( // Hide the view val viewRegister = (this as Instruction35c).registerC - proxy(classDef) - .mutableClass + mutableClassBy(classDef) .findMutableMethodOf(method) .injectHideViewCall( insertIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt index 7629d1760d..284567fec7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val getPremiumViewFingerprint = fingerprint { +internal val getPremiumViewFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returns("V") parameters("I", "I") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt index 413c569400..c929bf4f7d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt @@ -41,7 +41,7 @@ val hideGetPremiumPatch = bytecodePatch( ) getPremiumViewFingerprint.method.apply { - val startIndex = getPremiumViewFingerprint.patternMatch!!.startIndex + val startIndex = getPremiumViewFingerprint.instructionMatches.first().index val measuredWidthRegister = getInstruction(startIndex).registerA val measuredHeightInstruction = getInstruction(startIndex + 1) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/video/Fingerprints.kt index 91cc0e8dfa..2ccd68aa4b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/video/Fingerprints.kt @@ -2,10 +2,9 @@ package app.revanced.patches.youtube.ad.video import app.revanced.patcher.fingerprint -internal val loadVideoAdsFingerprint = fingerprint { +internal val loadVideoAdsFingerprint by fingerprint { strings( "TriggerBundle doesn't have the required metadata specified by the trigger ", - "Tried to enter slot with no assigned slotAdapter", - "Trying to enter a slot when a slot of same type and physical position is already active. Its status: ", + "Ping migration no associated ping bindings for activated trigger: ", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt index b252875901..4e010f2ada 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val createDialogFingerprint = fingerprint { +internal val createDialogFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED) returns("V") parameters("L", "L", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt index 9c91ca108c..28c2c28694 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt @@ -87,7 +87,7 @@ val downloadsPatch = bytecodePatch( // Main activity is used to launch downloader intent. mainActivityOnCreateFingerprint.method.addInstruction( 1, - "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V" + "invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->setMainActivity(Landroid/app/Activity;)V" ) offlineVideoEndpointFingerprint.method.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/Fingerprints.kt index f10fc8e834..abd9a1e125 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.youtube.interaction.downloads -import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint +import app.revanced.patcher.string +import com.android.tools.smali.dexlib2.AccessFlags -internal val offlineVideoEndpointFingerprint = fingerprint { +internal val offlineVideoEndpointFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters( @@ -12,5 +13,7 @@ internal val offlineVideoEndpointFingerprint = fingerprint { "Ljava/lang/String", // VideoId "L", ) - strings("Object is not an offlineable video: ") + instructions( + string("Object is not an offlineable video: ") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt index 162b690905..6ee07c8110 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt @@ -11,8 +11,6 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.findFreeRegister -import app.revanced.util.indexOfFirstInstructionOrThrow -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference @@ -37,38 +35,46 @@ val enableSeekbarTappingPatch = bytecodePatch( // Find the required methods to tap the seekbar. val seekbarTappingMethods = onTouchEventHandlerFingerprint.let { - fun getMethodReference(index: Int) = it.method.getInstruction(index) + fun getReference(index: Int) = it.method.getInstruction(index) .reference as MethodReference listOf( - getMethodReference(it.patternMatch!!.startIndex), - getMethodReference(it.patternMatch!!.endIndex) + getReference(it.instructionMatches.first().index), + getReference(it.instructionMatches.last().index) ) } - seekbarTappingFingerprint.method.apply { - val pointIndex = indexOfNewPointInstruction(this) - val invokeIndex = indexOfFirstInstructionOrThrow(pointIndex, Opcode.INVOKE_VIRTUAL) - val insertIndex = invokeIndex + 1 + seekbarTappingFingerprint.let { + val insertIndex = it.instructionMatches.last().index + 1 - val thisInstanceRegister = getInstruction(invokeIndex).registerC - val xAxisRegister = this.getInstruction(pointIndex).registerD - val freeRegister = findFreeRegister(insertIndex, thisInstanceRegister, xAxisRegister) + it.method.apply { + val thisInstanceRegister = getInstruction( + insertIndex - 1 + ).registerC - val oMethod = seekbarTappingMethods[0] - val nMethod = seekbarTappingMethods[1] + val xAxisRegister = this.getInstruction( + it.instructionMatches[2].index + ).registerD - addInstructionsWithLabels( - insertIndex, - """ - invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->seekbarTappingEnabled()Z - move-result v$freeRegister - if-eqz v$freeRegister, :disabled - invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $oMethod - invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $nMethod - """, - ExternalLabel("disabled", getInstruction(insertIndex)), - ) + val freeRegister = findFreeRegister( + insertIndex, thisInstanceRegister, xAxisRegister + ) + + val oMethod = seekbarTappingMethods[0] + val nMethod = seekbarTappingMethods[1] + + addInstructionsWithLabels( + insertIndex, + """ + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->seekbarTappingEnabled()Z + move-result v$freeRegister + if-eqz v$freeRegister, :disabled + invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $oMethod + invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $nMethod + """, + ExternalLabel("disabled", getInstruction(insertIndex)), + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt index 1a19d5b913..f1b1a32776 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt @@ -42,7 +42,7 @@ val enableSlideToSeekPatch = bytecodePatch( // Restore the behaviour to slide to seek. - val checkIndex = slideToSeekFingerprint.patternMatch!!.startIndex + val checkIndex = slideToSeekFingerprint.instructionMatches.first().index val checkReference = slideToSeekFingerprint.method.getInstruction(checkIndex) .getReference()!! @@ -78,7 +78,7 @@ val enableSlideToSeekPatch = bytecodePatch( disableFastForwardNoticeFingerprint, ).forEach { fingerprint -> fingerprint.method.apply { - val targetIndex = fingerprint.patternMatch!!.endIndex + val targetIndex = fingerprint.instructionMatches.last().index val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -91,17 +91,19 @@ val enableSlideToSeekPatch = bytecodePatch( } } } else { - disableFastForwardLegacyFingerprint.method.apply { - val insertIndex = disableFastForwardLegacyFingerprint.patternMatch!!.endIndex + 1 - val targetRegister = getInstruction(insertIndex).registerA - - addInstructions( - insertIndex, - """ - invoke-static { v$targetRegister }, $extensionMethodDescriptor - move-result v$targetRegister - """, - ) + disableFastForwardLegacyFingerprint.let { + it.method.apply { + val insertIndex = it.instructionMatches.last().index + 1 + val targetRegister = getInstruction(insertIndex).registerA + + addInstructions( + insertIndex, + """ + invoke-static { v$targetRegister }, $extensionMethodDescriptor + move-result v$targetRegister + """, + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt index 37ad6f750b..5c53ff067c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt @@ -1,50 +1,60 @@ package app.revanced.patches.youtube.interaction.seekbar +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.newInstance +import app.revanced.patcher.opcode +import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater +import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_20_or_greater import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction -import app.revanced.util.indexOfFirstInstructionReversed import app.revanced.util.literal 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 import com.android.tools.smali.dexlib2.iface.reference.StringReference -internal val swipingUpGestureParentFingerprint = fingerprint { +internal val swipingUpGestureParentFingerprint by fingerprint { returns("Z") parameters() - literal { 45379021 } + instructions( + literal(45379021) // Swipe up fullscreen feature flag + ) } /** * Resolves using the class found in [swipingUpGestureParentFingerprint]. */ -internal val showSwipingUpGuideFingerprint = fingerprint { +internal val showSwipingUpGuideFingerprint by fingerprint { accessFlags(AccessFlags.FINAL) returns("Z") parameters() - literal { 1 } + instructions( + literal(1) + ) } /** * Resolves using the class found in [swipingUpGestureParentFingerprint]. */ -internal val allowSwipingUpGestureFingerprint = fingerprint { +internal val allowSwipingUpGestureFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") } -internal val disableFastForwardLegacyFingerprint = fingerprint { +internal val disableFastForwardLegacyFingerprint by fingerprint { returns("Z") parameters() opcodes(Opcode.MOVE_RESULT) - literal { 45411330 } + // Intent start flag only used in the subscription activity + literal {45411330} } -internal val disableFastForwardGestureFingerprint = fingerprint { +internal val disableFastForwardGestureFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() @@ -59,26 +69,51 @@ internal val disableFastForwardGestureFingerprint = fingerprint { } } -internal val disableFastForwardNoticeFingerprint = fingerprint { +internal val disableFastForwardNoticeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() - opcodes( - Opcode.CHECK_CAST, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, + instructions( + opcode(Opcode.CHECK_CAST), + // opcode(Opcode.IGET_OBJECT), // 20.25+ + methodCall(opcode = Opcode.INVOKE_VIRTUAL, returnType = "Z", maxAfter = 1), + opcode(Opcode.MOVE_RESULT, maxAfter = 0), ) custom { method, _ -> + // Code is found in different methods with different strings. + val findSearchLandingKey = (is_19_34_or_greater && !is_19_47_or_greater) + || is_20_19_or_greater + + method.name == "run" && method.indexOfFirstInstruction { + val string = getReference()?.string + string == "Failed to easy seek haptics vibrate." + || (findSearchLandingKey && string == "search_landing_cache_key") + } >= 0 + } +} + +/** + * For 20.19 and below, this matches the same method as [disableFastForwardNoticeFingerprint]. + * For 20.20+, this matches a different method. + */ +internal val customTapAndHoldFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("V") + parameters() + custom { method, _ -> + // Code is found in different methods with different strings. + val findSearchLandingKey = (is_19_34_or_greater && !is_19_47_or_greater) + || (is_20_19_or_greater && !is_20_20_or_greater) + method.name == "run" && method.indexOfFirstInstruction { - // In later targets the code is found in different methods with different strings. val string = getReference()?.string - string == "Failed to easy seek haptics vibrate." || string == "search_landing_cache_key" + string == "Failed to easy seek haptics vibrate." + || (findSearchLandingKey && string == "search_landing_cache_key") } >= 0 } } -internal val onTouchEventHandlerFingerprint = fingerprint { +internal val onTouchEventHandlerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.PUBLIC) returns("Z") parameters("L") @@ -101,24 +136,25 @@ internal val onTouchEventHandlerFingerprint = fingerprint { custom { method, _ -> method.name == "onTouchEvent" } } -internal val seekbarTappingFingerprint = fingerprint { +internal val seekbarTappingFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") - parameters("L") - custom { method, _ -> - method.name == "onTouchEvent" - && method.containsLiteralInstruction(Integer.MAX_VALUE.toLong()) - && indexOfNewPointInstruction(method) >= 0 - } -} + parameters("Landroid/view/MotionEvent;") + instructions( + literal(Int.MAX_VALUE), + + newInstance("Landroid/graphics/Point;"), + methodCall(smali = "Landroid/graphics/Point;->(II)V", maxAfter = 0), + methodCall(smali = "Lj\$/util/Optional;->of(Ljava/lang/Object;)Lj\$/util/Optional;", maxAfter = 0), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), + fieldAccess(opcode = Opcode.IPUT_OBJECT, type = "Lj\$/util/Optional;", maxAfter = 0), -internal fun indexOfNewPointInstruction(method: Method) = method.indexOfFirstInstructionReversed { - val reference = getReference() - reference?.definingClass == "Landroid/graphics/Point;" - && reference.name == "" + opcode(Opcode.INVOKE_VIRTUAL, maxAfter = 10) + ) + custom { method, _ -> method.name == "onTouchEvent" } } -internal val slideToSeekFingerprint = fingerprint { +internal val slideToSeekFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") parameters("Landroid/view/View;", "F") @@ -131,9 +167,11 @@ internal val slideToSeekFingerprint = fingerprint { literal { 67108864 } } -internal val fullscreenSeekbarThumbnailsQualityFingerprint = fingerprint { +internal val fullscreenSeekbarThumbnailsQualityFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { 45399684L } + instructions( + literal(45399684L) // Video stream seekbar thumbnails feature flag. + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt index b502be1ae5..66a79003f8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatch.kt @@ -13,6 +13,7 @@ import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen +import java.util.logging.Logger private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;" diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt index e1161ea13d..2c7dc336b6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt @@ -1,10 +1,10 @@ package app.revanced.patches.youtube.interaction.swipecontrols import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal import com.android.tools.smali.dexlib2.AccessFlags -internal val swipeControlsHostActivityFingerprint = fingerprint { +internal val swipeControlsHostActivityFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters() custom { method, _ -> @@ -12,12 +12,9 @@ internal val swipeControlsHostActivityFingerprint = fingerprint { } } -internal const val SWIPE_CHANGE_VIDEO_FEATURE_FLAG = 45631116L - -internal val swipeChangeVideoFingerprint = fingerprint { +internal val swipeChangeVideoFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - parameters("L") - literal { - SWIPE_CHANGE_VIDEO_FEATURE_FLAG - } + instructions( + literal(45631116L) // Swipe to change fullscreen video feature flag. + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt index 1814de194c..3115058413 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt @@ -124,10 +124,12 @@ val swipeControlsPatch = bytecodePatch( // region patch to enable/disable swipe to change video. if (is_19_43_or_greater) { - swipeChangeVideoFingerprint.method.insertLiteralOverride( - SWIPE_CHANGE_VIDEO_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->allowSwipeChangeVideo(Z)Z" - ) + swipeChangeVideoFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.last().index, + "$EXTENSION_CLASS_DESCRIPTOR->allowSwipeChangeVideo(Z)Z" + ) + } } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt index 1a04db3c9d..0e49f0eacb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt @@ -52,7 +52,7 @@ val autoCaptionsPatch = bytecodePatch( """ ) - mapOf( + arrayOf( startVideoInformerFingerprint to 0, storyboardRendererDecoderRecommendedLevelFingerprint to 1 ).forEach { (fingerprint, enabled) -> diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/Fingerprints.kt index c657b72ec2..3ecbb437e5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val startVideoInformerFingerprint = fingerprint { +internal val startVideoInformerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") opcodes( @@ -14,14 +14,14 @@ internal val startVideoInformerFingerprint = fingerprint { strings("pc") } -internal val storyboardRendererDecoderRecommendedLevelFingerprint = fingerprint { +internal val storyboardRendererDecoderRecommendedLevelFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("L") strings("#-1#") } -internal val subtitleTrackFingerprint = fingerprint { +internal val subtitleTrackFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt index 3b831007a3..1896516c4d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt @@ -20,7 +20,7 @@ private val iconResourceFileNames = arrayOf( "ic_launcher_round", ).map { "$it.png" }.toTypedArray() -private val iconResourceFileNamesNew = mapOf( +private val iconResourceFileNamesNew = arrayOf( "adaptiveproduct_youtube_foreground_color_108" to "adaptiveproduct_youtube_2024_q4_foreground_color_108", "adaptiveproduct_youtube_background_color_108" to "adaptiveproduct_youtube_2024_q4_background_color_108", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch.kt index 7dc90c7d7f..3ab1d704b4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch.kt @@ -19,15 +19,15 @@ private const val PREMIUM_HEADER_OPTION = "premium*header" private const val REVANCED_HEADER_OPTION = "revanced*" private const val REVANCED_BORDERLESS_HEADER_OPTION = "revanced*borderless" -private val targetResourceDirectoryNames = mapOf( +private val targetResourceDirectoryNames = arrayOf( "xxxhdpi" to "512px x 192px", "xxhdpi" to "387px x 144px", "xhdpi" to "258px x 96px", "hdpi" to "194px x 72px", "mdpi" to "129px x 48px", -).map { (dpi, dim) -> +).associate { (dpi, dim) -> "drawable-$dpi" to dim -}.toMap() +} private val variants = arrayOf("light", "dark") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt index a4e65eb28b..49868a731f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt @@ -1,53 +1,68 @@ package app.revanced.patches.youtube.layout.buttons.navigation -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -import app.revanced.util.literal - -internal const val ANDROID_AUTOMOTIVE_STRING = "Android Automotive" +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal val addCreateButtonViewFingerprint = fingerprint { - strings("Android Wear", ANDROID_AUTOMOTIVE_STRING) +internal val addCreateButtonViewFingerprint by fingerprint { + instructions( + string("Android Wear"), + opcode(Opcode.IF_EQZ), + string("Android Automotive", maxAfter = 0), + ) } -internal val createPivotBarFingerprint = fingerprint { +internal val createPivotBarFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") parameters( "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;", "Landroid/widget/TextView;", "Ljava/lang/CharSequence;", ) - opcodes( - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID, + instructions( + methodCall(definingClass = "Landroid/widget/TextView;", name = "setText"), + opcode(Opcode.RETURN_VOID) ) } -internal const val TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG = 45400535L - -internal val translucentNavigationStatusBarFeatureFlagFingerprint = fingerprint { +internal val animatedNavigationTabsFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") - literal { TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG } + instructions( + literal(45680008L) + ) } -internal const val TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG = 45630927L +internal val translucentNavigationStatusBarFeatureFlagFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + instructions( + literal(45400535L) // Translucent status bar feature flag. + ) +} -internal val translucentNavigationButtonsFeatureFlagFingerprint = fingerprint { +/** + * YouTube nav buttons. + */ +internal val translucentNavigationButtonsFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") - literal { TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG } + instructions( + literal(45630927L) // Translucent navigation bar buttons feature flag. + ) } /** - * The device on screen back/home/recent buttons. + * Device on screen back/home/recent buttons. */ -internal const val TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG = 45632194L - -internal val translucentNavigationButtonsSystemFeatureFlagFingerprint = fingerprint { +internal val translucentNavigationButtonsSystemFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") - literal { TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG } + instructions( + literal(45632194L) // Translucent system buttons feature flag. + ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt index 92d6709657..297b2b27aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt @@ -13,15 +13,13 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.navigation.hookNavigationButtonCreated import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_15_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.insertLiteralOverride 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.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/NavigationButtonsPatch;" @@ -70,6 +68,12 @@ val navigationButtonsPatch = bytecodePatch( ) } + if (is_20_15_or_greater) { + PreferenceScreen.GENERAL_LAYOUT.addPreferences( + SwitchPreference("revanced_navigation_bar_animations") + ) + } + PreferenceScreen.GENERAL_LAYOUT.addPreferences( PreferenceScreenPreference( key = "revanced_navigation_buttons_screen", @@ -79,59 +83,70 @@ val navigationButtonsPatch = bytecodePatch( ) // Switch create with notifications button. - addCreateButtonViewFingerprint.method.apply { - val stringIndex = addCreateButtonViewFingerprint.stringMatches!!.find { match -> - match.string == ANDROID_AUTOMOTIVE_STRING - }!!.index - - val conditionalCheckIndex = stringIndex - 1 - val conditionRegister = - getInstruction(conditionalCheckIndex).registerA - - addInstructions( - conditionalCheckIndex, - """ - invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z - move-result v$conditionRegister - """, - ) + addCreateButtonViewFingerprint.let { + it.method.apply { + val conditionalCheckIndex = it.instructionMatches[1].index + val conditionRegister = + getInstruction(conditionalCheckIndex).registerA + + addInstructions( + conditionalCheckIndex, + """ + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->switchCreateWithNotificationButton()Z + move-result v$conditionRegister + """, + ) + } } // Hide navigation button labels. - createPivotBarFingerprint.method.apply { - val setTextIndex = indexOfFirstInstructionOrThrow { - getReference()?.name == "setText" + createPivotBarFingerprint.let { + it.method.apply { + val setTextIndex = it.instructionMatches.first().index + val targetRegister = getInstruction(setTextIndex).registerC + + addInstruction( + setTextIndex, + "invoke-static { v$targetRegister }, " + + "$EXTENSION_CLASS_DESCRIPTOR->hideNavigationButtonLabels(Landroid/widget/TextView;)V", + ) } - - val targetRegister = getInstruction(setTextIndex).registerC - - addInstruction( - setTextIndex, - "invoke-static { v$targetRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->hideNavigationButtonLabels(Landroid/widget/TextView;)V", - ) } // Hook navigation button created, in order to hide them. hookNavigationButtonCreated(EXTENSION_CLASS_DESCRIPTOR) - // Force on/off translucent effect on status bar and navigation buttons. if (is_19_25_or_greater) { - translucentNavigationStatusBarFeatureFlagFingerprint.method.insertLiteralOverride( - TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z", - ) + translucentNavigationStatusBarFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z", + ) + } - translucentNavigationButtonsFeatureFlagFingerprint.method.insertLiteralOverride( - TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", - ) + translucentNavigationButtonsFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", + ) + } - translucentNavigationButtonsSystemFeatureFlagFingerprint.method.insertLiteralOverride( - TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", - ) + translucentNavigationButtonsSystemFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", + ) + } + } + + if (is_20_15_or_greater) { + animatedNavigationTabsFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->useAnimatedNavigationButtons(Z)Z" + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt index 7cc63f0fe6..dc4146b979 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt @@ -1,30 +1,23 @@ package app.revanced.patches.youtube.layout.buttons.overlay import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.literal +import app.revanced.patcher.methodCall +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags -internal val playerControlsPreviousNextOverlayTouchFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("V") - strings("1.0x") - custom { methodDef, _ -> - methodDef.containsLiteralInstruction(playerControlPreviousButtonTouchArea) && - methodDef.containsLiteralInstruction(playerControlNextButtonTouchArea) - } -} - -internal val mediaRouteButtonFingerprint = fingerprint { +internal val mediaRouteButtonFingerprint by fingerprint { parameters("I") custom { methodDef, _ -> methodDef.definingClass.endsWith("/MediaRouteButton;") && methodDef.name == "setVisibility" } } -internal val inflateControlsGroupLayoutStubFingerprint = fingerprint { +internal val inflateControlsGroupLayoutStubFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() returns("V") - literal { controlsButtonGroupLayoutStub } + instructions( + resourceLiteral("id", "youtube_controls_button_group_layout_stub"), + methodCall(name = "inflate") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt index 10bed407ca..19c26bc3d3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt @@ -5,42 +5,25 @@ 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.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.shared.layoutConstructorFingerprint import app.revanced.patches.youtube.shared.subtitleButtonControllerFingerprint -import app.revanced.util.* +import app.revanced.util.findFreeRegister +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstResourceIdOrThrow 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.reference.MethodReference -internal var playerControlPreviousButtonTouchArea = -1L - private set -internal var playerControlNextButtonTouchArea = -1L - private set -internal var controlsButtonGroupLayoutStub = -1L - private set - -private val hidePlayerOverlayButtonsResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - playerControlPreviousButtonTouchArea = resourceMappings["id", "player_control_previous_button_touch_area"] - playerControlNextButtonTouchArea = resourceMappings["id", "player_control_next_button_touch_area"] - controlsButtonGroupLayoutStub = resourceMappings["id", "youtube_controls_button_group_layout_stub"] - } -} - private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/HidePlayerOverlayButtonsPatch;" @@ -53,7 +36,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, - hidePlayerOverlayButtonsResourcePatch, + resourceMappingPatch // Used by fingerprints ) compatibleWith( @@ -79,21 +62,19 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( // region Hide player next/previous button. - playerControlsPreviousNextOverlayTouchFingerprint.method.apply { - val resourceIndex = indexOfFirstLiteralInstructionOrThrow(playerControlPreviousButtonTouchArea) - - val insertIndex = indexOfFirstInstructionOrThrow(resourceIndex) { - opcode == Opcode.INVOKE_STATIC && - getReference()?.parameterTypes?.firstOrNull() == "Landroid/view/View;" - } + layoutConstructorFingerprint.let { + it.clearMatch() // Fingerprint is shared with other patches. - val viewRegister = getInstruction(insertIndex).registerC + it.method.apply { + val insertIndex = it.instructionMatches.last().index + val viewRegister = getInstruction(insertIndex).registerC - addInstruction( - insertIndex, - "invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR" + - "->hidePreviousNextButtons(Landroid/view/View;)V", - ) + addInstruction( + insertIndex, + "invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR" + + "->hidePreviousNextButtons(Landroid/view/View;)V", + ) + } } // endregion @@ -153,27 +134,21 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( // region Hide player control buttons background. - inflateControlsGroupLayoutStubFingerprint.method.apply { - val controlsButtonGroupLayoutStubResIdConstIndex = - indexOfFirstLiteralInstructionOrThrow(controlsButtonGroupLayoutStub) - val inflateControlsGroupLayoutStubIndex = - indexOfFirstInstruction(controlsButtonGroupLayoutStubResIdConstIndex) { - getReference()?.name == "inflate" - } - - val freeRegister = findFreeRegister(inflateControlsGroupLayoutStubIndex) - val hidePlayerControlButtonsBackgroundDescriptor = - "$EXTENSION_CLASS_DESCRIPTOR->hidePlayerControlButtonsBackground(Landroid/view/View;)V" - - addInstructions( - inflateControlsGroupLayoutStubIndex + 1, - """ - # Move the inflated layout to a temporary register. - # The result of the inflate method is by default not moved to a register after the method is called. - move-result-object v$freeRegister - invoke-static { v$freeRegister }, $hidePlayerControlButtonsBackgroundDescriptor - """ - ) + inflateControlsGroupLayoutStubFingerprint.let { + it.method.apply { + val insertIndex = it.instructionMatches.last().index + 1 + val freeRegister = findFreeRegister(insertIndex) + + addInstructions( + insertIndex, + """ + # Move the inflated layout to a temporary register. + # The result of the inflate method is by default not moved to a register after the method is called. + move-result-object v$freeRegister + invoke-static { v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->hidePlayerControlButtonsBackground(Landroid/view/View;)V + """ + ) + } } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt index d160426385..765591a963 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt @@ -2,6 +2,8 @@ package app.revanced.patches.youtube.layout.formfactor import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.fieldAccess +import app.revanced.patcher.fingerprint import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch @@ -11,11 +13,8 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.navigation.hookNavigationButtonCreated import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ChangeFormFactorPatch;" @@ -50,24 +49,33 @@ val changeFormFactorPatch = bytecodePatch( hookNavigationButtonCreated(EXTENSION_CLASS_DESCRIPTOR) - createPlayerRequestBodyWithModelFingerprint.method.apply { - val formFactorEnumClass = formFactorEnumConstructorFingerprint.originalClassDef.type + val createPlayerRequestBodyWithModelFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("L") + parameters() + instructions( + fieldAccess(smali = "Landroid/os/Build;->MODEL:Ljava/lang/String;"), + fieldAccess( + definingClass = { formFactorEnumConstructorFingerprint.originalClassDef.type }, + type = { "I" }, + maxAfter = 50 + ) + ) + } - val index = indexOfFirstInstructionOrThrow { - val reference = getReference() - opcode == Opcode.IGET && - reference?.definingClass == formFactorEnumClass && - reference.type == "I" - } - val register = getInstruction(index).registerA + createPlayerRequestBodyWithModelFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA - addInstructions( - index + 1, - """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getFormFactor(I)I - move-result v$register - """ - ) + addInstructions( + index + 1, + """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getFormFactor(I)I + move-result v$register + """ + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/Fingerprints.kt index d1f1535ebf..6ffedaf77a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/Fingerprints.kt @@ -1,14 +1,9 @@ package app.revanced.patches.youtube.layout.formfactor import app.revanced.patcher.fingerprint -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 -internal val formFactorEnumConstructorFingerprint = fingerprint { +internal val formFactorEnumConstructorFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) strings( "UNKNOWN_FORM_FACTOR", @@ -17,33 +12,3 @@ internal val formFactorEnumConstructorFingerprint = fingerprint { "AUTOMOTIVE_FORM_FACTOR" ) } - -internal val createPlayerRequestBodyWithModelFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("L") - parameters() - opcodes(Opcode.OR_INT_LIT16) - custom { method, _ -> - method.indexOfModelInstruction() >= 0 && - method.indexOfReleaseInstruction() >= 0 - } -} - -private fun Method.indexOfModelInstruction() = - indexOfFirstInstruction { - val reference = getReference() - - reference?.definingClass == "Landroid/os/Build;" && - reference.name == "MODEL" && - reference.type == "Ljava/lang/String;" - } - -internal fun Method.indexOfReleaseInstruction(): Int = - indexOfFirstInstruction { - val reference = getReference() - - reference?.definingClass == "Landroid/os/Build${'$'}VERSION;" && - reference.name == "RELEASE" && - reference.type == "Ljava/lang/String;" - } - diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt index 59d859e800..dfd8f3110e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt @@ -2,9 +2,12 @@ package app.revanced.patches.youtube.layout.hide.endscreencards import app.revanced.patcher.fingerprint import app.revanced.util.literal +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val layoutCircleFingerprint = fingerprint { +internal val layoutCircleFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters() returns("Landroid/view/View;") opcodes( Opcode.CONST, @@ -16,7 +19,9 @@ internal val layoutCircleFingerprint = fingerprint { literal { layoutCircle } } -internal val layoutIconFingerprint = fingerprint { +internal val layoutIconFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters() returns("Landroid/view/View;") opcodes( Opcode.INVOKE_VIRTUAL, @@ -27,7 +32,9 @@ internal val layoutIconFingerprint = fingerprint { literal { layoutIcon } } -internal val layoutVideoFingerprint = fingerprint { +internal val layoutVideoFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC) + parameters() returns("Landroid/view/View;") opcodes( Opcode.CONST, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt index 6824ce50f3..0dcf70caad 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt @@ -6,9 +6,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen @@ -36,7 +35,7 @@ private val hideEndscreenCardsResourcePatch = resourcePatch { SwitchPreference("revanced_hide_endscreen_cards"), ) - fun idOf(name: String) = resourceMappings["layout", "endscreen_element_layout_$name"] + fun idOf(name: String) = getResourceId("layout", "endscreen_element_layout_$name") layoutCircle = idOf("circle") layoutIcon = idOf("icon") @@ -74,7 +73,7 @@ val hideEndscreenCardsPatch = bytecodePatch( layoutVideoFingerprint, ).forEach { fingerprint -> fingerprint.method.apply { - val insertIndex = fingerprint.patternMatch!!.endIndex + 1 + val insertIndex = fingerprint.instructionMatches.last().index + 1 val viewRegister = getInstruction(insertIndex - 1).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt index 887963e56e..97641725fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt @@ -7,19 +7,19 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val autoNavConstructorFingerprint = fingerprint { +internal val autoNavConstructorFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) strings("main_app_autonav") } -internal val autoNavStatusFingerprint = fingerprint { +internal val autoNavStatusFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() } -internal val removeOnLayoutChangeListenerFingerprint = fingerprint { +internal val removeOnLayoutChangeListenerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt index 1b8af4296c..b656ede82a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt @@ -47,7 +47,7 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch( ) removeOnLayoutChangeListenerFingerprint.let { - val endScreenMethod = navigate(it.originalMethod).to(it.patternMatch!!.endIndex).stop() + val endScreenMethod = navigate(it.originalMethod).to(it.instructionMatches.last().index).stop() endScreenMethod.apply { val autoNavStatusMethodName = autoNavStatusFingerprint.match( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/Fingerprints.kt index b619020878..fff4d86218 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.youtube.layout.hide.fullscreenambientmode import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal val setFullScreenBackgroundColorFingerprint = fingerprint { +internal val setFullScreenBackgroundColorFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) parameters("Z", "I", "I", "I", "I") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt index e83689607d..3e7aa5bda5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt @@ -1,68 +1,45 @@ package app.revanced.patches.youtube.layout.hide.general +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import app.revanced.patches.youtube.layout.searchbar.wideSearchbarLayoutFingerprint import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val hideShowMoreButtonFingerprint = fingerprint { - opcodes( - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - ) - literal { expandButtonDownId } -} - -/** - * 20.12+ - */ -internal val parseElementFromBufferFingerprint = fingerprint { - parameters("L", "L", "[B", "L", "L") - opcodes( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - ) - strings("Failed to parse Element") // String is a partial match. -} - -/** - * 20.07+ - */ -internal val parseElementFromBufferLegacy2007Fingerprint = fingerprint { - parameters("L", "L", "[B", "L", "L") - opcodes( - Opcode.IGET_OBJECT, - Opcode.IGET_BOOLEAN, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, +internal val hideShowMoreButtonFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) + instructions( + resourceLiteral("layout", "expand_button_down"), + methodCall(smali = "Landroid/view/View;->inflate(Landroid/content/Context;ILandroid/view/ViewGroup;)Landroid/view/View;"), + opcode(Opcode.MOVE_RESULT_OBJECT) ) - strings("Failed to parse Element") // String is a partial match. } -/** - * 19.01 - 20.06 - */ -internal val parseElementFromBufferLegacy1901Fingerprint = fingerprint { +internal val parseElementFromBufferFingerprint by fingerprint { parameters("L", "L", "[B", "L", "L") - opcodes( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, + instructions( + opcode(Opcode.IGET_OBJECT), + // IGET_BOOLEAN // 20.07+ + opcode(Opcode.INVOKE_INTERFACE, maxAfter = 1), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), + string("Failed to parse Element", partialMatch = true) ) - strings("Failed to parse Element") // String is a partial match. } -internal val playerOverlayFingerprint = fingerprint { +internal val playerOverlayFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") - strings("player_overlay_in_video_programming") + instructions( + string("player_overlay_in_video_programming") + ) } -internal val showWatermarkFingerprint = fingerprint { +internal val showWatermarkFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "L") @@ -71,14 +48,16 @@ internal val showWatermarkFingerprint = fingerprint { /** * Matches same method as [wideSearchbarLayoutFingerprint]. */ -internal val yoodlesImageViewFingerprint = fingerprint { +internal val yoodlesImageViewFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") parameters("L", "L") - literal { youTubeLogo } + instructions( + resourceLiteral("id", "youtube_logo") + ) } -internal val crowdfundingBoxFingerprint = fingerprint { +internal val crowdfundingBoxFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.INVOKE_VIRTUAL, @@ -88,7 +67,7 @@ internal val crowdfundingBoxFingerprint = fingerprint { literal { crowdfundingBoxId } } -internal val albumCardsFingerprint = fingerprint { +internal val albumCardsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.MOVE_RESULT_OBJECT, @@ -101,9 +80,8 @@ internal val albumCardsFingerprint = fingerprint { literal { albumCardId } } -internal val filterBarHeightFingerprint = fingerprint { +internal val filterBarHeightFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") opcodes( Opcode.CONST, Opcode.INVOKE_VIRTUAL, @@ -113,9 +91,8 @@ internal val filterBarHeightFingerprint = fingerprint { literal { filterBarHeightId } } -internal val relatedChipCloudFingerprint = fingerprint { +internal val relatedChipCloudFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") opcodes( Opcode.CONST, Opcode.INVOKE_VIRTUAL, @@ -124,9 +101,8 @@ internal val relatedChipCloudFingerprint = fingerprint { literal { relatedChipCloudMarginId } } -internal val searchResultsChipBarFingerprint = fingerprint { +internal val searchResultsChipBarFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") opcodes( Opcode.CONST, Opcode.INVOKE_VIRTUAL, @@ -137,13 +113,13 @@ internal val searchResultsChipBarFingerprint = fingerprint { literal { barContainerHeightId } } -internal val showFloatingMicrophoneButtonFingerprint = fingerprint { +internal val showFloatingMicrophoneButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() - opcodes( - Opcode.IGET_BOOLEAN, - Opcode.IF_EQZ, + instructions( + resourceLiteral("id", "fab"), + checkCast("/FloatingActionButton;", maxAfter = 10), + opcode(Opcode.IGET_BOOLEAN, maxAfter = 10) ) - literal { fabButtonId } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt index cebdb7c2a9..e954c66c7d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt @@ -13,22 +13,21 @@ import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings -import app.revanced.patches.shared.misc.settings.preference.* +import app.revanced.patches.shared.misc.settings.preference.InputType +import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference +import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference +import app.revanced.patches.shared.misc.settings.preference.SwitchPreference +import app.revanced.patches.shared.misc.settings.preference.TextPreference import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch -import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.findFreeRegister import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -36,66 +35,45 @@ 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.MethodReference -var expandButtonDownId = -1L +internal var albumCardId = -1L private set -var albumCardId = -1L +internal var crowdfundingBoxId = -1L private set -var crowdfundingBoxId = -1L +internal var filterBarHeightId = -1L private set -var youTubeLogo = -1L +internal var relatedChipCloudMarginId = -1L private set -var filterBarHeightId = -1L - private set -var relatedChipCloudMarginId = -1L - private set -var barContainerHeightId = -1L - private set -var fabButtonId = -1L +internal var barContainerHeightId = -1L private set private val hideLayoutComponentsResourcePatch = resourcePatch { dependsOn(resourceMappingPatch) execute { - expandButtonDownId = resourceMappings[ - "layout", - "expand_button_down", - ] - - albumCardId = resourceMappings[ + albumCardId = getResourceId( "layout", "album_card", - ] + ) - crowdfundingBoxId = resourceMappings[ + crowdfundingBoxId = getResourceId( "layout", "donation_companion", - ] - - youTubeLogo = resourceMappings[ - "id", - "youtube_logo", - ] + ) - relatedChipCloudMarginId = resourceMappings[ + relatedChipCloudMarginId = getResourceId( "layout", "related_chip_cloud_reduced_margins", - ] + ) - filterBarHeightId = resourceMappings[ + filterBarHeightId = getResourceId( "dimen", "filter_bar_height", - ] + ) - barContainerHeightId = resourceMappings[ + barContainerHeightId = getResourceId( "dimen", "bar_container_height", - ] - - fabButtonId = resourceMappings[ - "id", - "fab", - ] + ) } } @@ -121,6 +99,7 @@ val hideLayoutComponentsPatch = bytecodePatch( addResourcesPatch, hideLayoutComponentsResourcePatch, navigationBarHookPatch, + resourceMappingPatch ) compatibleWith( @@ -247,32 +226,29 @@ val hideLayoutComponentsPatch = bytecodePatch( // region Mix playlists - (if (is_20_09_or_greater) parseElementFromBufferFingerprint - else if (is_20_07_or_greater) parseElementFromBufferLegacy2007Fingerprint - else parseElementFromBufferLegacy1901Fingerprint).let { - it.method.apply { - val byteArrayParameter = "p3" - val startIndex = it.patternMatch!!.startIndex - val conversionContextRegister = getInstruction(startIndex).registerA - val returnEmptyComponentInstruction = instructions.last { it.opcode == Opcode.INVOKE_STATIC } - val returnEmptyComponentRegister = (returnEmptyComponentInstruction as FiveRegisterInstruction).registerC - val insertIndex = startIndex + 1 - val freeRegister = findFreeRegister(insertIndex, conversionContextRegister, returnEmptyComponentRegister) + parseElementFromBufferFingerprint.method.apply { + val startIndex = parseElementFromBufferFingerprint.instructionMatches.first().index + val insertIndex = startIndex + 1 - addInstructionsWithLabels( - insertIndex, - """ - invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z - move-result v$freeRegister - if-eqz v$freeRegister, :show - move-object v$returnEmptyComponentRegister, p1 # Required for 19.47 - goto :return_empty_component - :show - nop - """, - ExternalLabel("return_empty_component", returnEmptyComponentInstruction), - ) - } + val byteArrayParameter = "p3" + val conversionContextRegister = getInstruction(startIndex).registerA + val returnEmptyComponentInstruction = instructions.last { it.opcode == Opcode.INVOKE_STATIC } + val returnEmptyComponentRegister = (returnEmptyComponentInstruction as FiveRegisterInstruction).registerC + val freeRegister = findFreeRegister(insertIndex, conversionContextRegister, returnEmptyComponentRegister) + + addInstructionsWithLabels( + insertIndex, + """ + invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z + move-result v$freeRegister + if-eqz v$freeRegister, :show + move-object v$returnEmptyComponentRegister, p1 # Required for 19.47 + goto :return_empty_component + :show + nop + """, + ExternalLabel("return_empty_component", returnEmptyComponentInstruction), + ) } // endregion @@ -299,7 +275,7 @@ val hideLayoutComponentsPatch = bytecodePatch( // region Show more button hideShowMoreButtonFingerprint.method.apply { - val moveRegisterIndex = hideShowMoreButtonFingerprint.patternMatch!!.endIndex + val moveRegisterIndex = hideShowMoreButtonFingerprint.instructionMatches.last().index val viewRegister = getInstruction(moveRegisterIndex).registerA val insertIndex = moveRegisterIndex + 1 @@ -315,7 +291,7 @@ val hideLayoutComponentsPatch = bytecodePatch( // region crowdfunding box crowdfundingBoxFingerprint.let { it.method.apply { - val insertIndex = it.patternMatch!!.endIndex + val insertIndex = it.instructionMatches.last().index val objectRegister = getInstruction(insertIndex).registerA addInstruction( @@ -332,7 +308,7 @@ val hideLayoutComponentsPatch = bytecodePatch( albumCardsFingerprint.let { it.method.apply { - val checkCastAnchorIndex = it.patternMatch!!.endIndex + val checkCastAnchorIndex = it.instructionMatches.last().index val insertIndex = checkCastAnchorIndex + 1 val register = getInstruction(checkCastAnchorIndex).registerA @@ -348,18 +324,19 @@ val hideLayoutComponentsPatch = bytecodePatch( // region hide floating microphone - showFloatingMicrophoneButtonFingerprint.method.apply { - val literalIndex = indexOfFirstLiteralInstructionOrThrow(fabButtonId) - val booleanIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.IGET_BOOLEAN) - val register = getInstruction(booleanIndex).registerA + showFloatingMicrophoneButtonFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA - addInstructions( - booleanIndex + 1, - """ - invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z - move-result v$register - """ - ) + addInstructions( + index + 1, + """ + invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z + move-result v$register + """, + ) + } } // endregion @@ -401,11 +378,9 @@ val hideLayoutComponentsPatch = bytecodePatch( hookRegisterOffset: Int = 0, instructions: (Int) -> String, ) = method.apply { - val endIndex = patternMatch!!.endIndex - + val endIndex = instructionMatches.last().index val insertIndex = endIndex + insertIndexOffset - val register = - getInstruction(endIndex + hookRegisterOffset).registerA + val register = getInstruction(endIndex + hookRegisterOffset).registerA addInstructions(insertIndex, instructions(register)) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt index 5088472a1b..6b1b09d585 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt @@ -1,24 +1,29 @@ package app.revanced.patches.youtube.layout.hide.infocards import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val infocardsIncognitoFingerprint = fingerprint { +internal val infocardsIncognitoFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/Boolean;") parameters("L", "J") - strings("vibrator") + instructions( + string("vibrator") + ) } -internal val infocardsIncognitoParentFingerprint = fingerprint { +internal val infocardsIncognitoParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") - strings("player_overlay_info_card_teaser") + instructions( + string("player_overlay_info_card_teaser") + ) } -internal val infocardsMethodCallFingerprint = fingerprint { +internal val infocardsMethodCallFingerprint by fingerprint { opcodes( Opcode.INVOKE_VIRTUAL, Opcode.IGET_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt index 72758a5ed2..996d46d259 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt @@ -8,9 +8,8 @@ import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter @@ -37,10 +36,10 @@ private val hideInfocardsResourcePatch = resourcePatch { SwitchPreference("revanced_hide_info_cards"), ) - drawerResourceId = resourceMappings[ + drawerResourceId = getResourceId( "id", "info_cards_drawer_header", - ] + ) } } @@ -81,7 +80,7 @@ val hideInfoCardsPatch = bytecodePatch( val hideInfoCardsCallMethod = infocardsMethodCallFingerprint.method - val invokeInterfaceIndex = infocardsMethodCallFingerprint.patternMatch!!.endIndex + val invokeInterfaceIndex = infocardsMethodCallFingerprint.instructionMatches.last().index val toggleRegister = infocardsMethodCallFingerprint.method.implementation!!.registerCount - 1 hideInfoCardsCallMethod.addInstructionsWithLabels( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/Fingerprints.kt index 0ca1298631..81ec46a314 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/Fingerprints.kt @@ -1,14 +1,18 @@ package app.revanced.patches.youtube.layout.hide.relatedvideooverlay import app.revanced.patcher.fingerprint +import app.revanced.patches.shared.misc.mapping.resourceLiteral import app.revanced.util.literal +import org.stringtemplate.v4.compiler.Bytecode.instructions -internal val relatedEndScreenResultsParentFingerprint = fingerprint { +internal val relatedEndScreenResultsParentFingerprint by fingerprint { returns("V") - literal{ appRelatedEndScreenResults } + instructions( + resourceLiteral("layout", "app_related_endscreen_results") + ) } -internal val relatedEndScreenResultsFingerprint = fingerprint { +internal val relatedEndScreenResultsFingerprint by fingerprint { returns("V") parameters( "I", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/HideRelatedVideoOverlayPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/HideRelatedVideoOverlayPatch.kt index 76b0de33b2..1ebd96c3bc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/HideRelatedVideoOverlayPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/relatedvideooverlay/HideRelatedVideoOverlayPatch.kt @@ -3,33 +3,14 @@ package app.revanced.patches.youtube.layout.hide.relatedvideooverlay 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.resourcePatch +import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patcher.util.smali.ExternalLabel - -internal var appRelatedEndScreenResults = -1L - private set - -private val hideRelatedVideoOverlayResourcePatch = resourcePatch { - dependsOn( - resourceMappingPatch, - ) - - execute { - appRelatedEndScreenResults = resourceMappings[ - "layout", - "app_related_endscreen_results", - ] - } -} private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/HideRelatedVideoOverlayPatch;" @@ -43,7 +24,7 @@ val hideRelatedVideoOverlayPatch = bytecodePatch( settingsPatch, sharedExtensionPatch, addResourcesPatch, - hideRelatedVideoOverlayResourcePatch, + resourceMappingPatch, ) compatibleWith( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt index 412cd40068..d81f67ccda 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt @@ -46,27 +46,27 @@ val disableRollingNumberAnimationPatch = bytecodePatch( // Animations are disabled by preventing an Image from being applied to the text span, // which prevents the animations from appearing. + rollingNumberTextViewAnimationUpdateFingerprint.let { + val blockStartIndex = it.instructionMatches.first().index + val blockEndIndex = it.instructionMatches.last().index + 1 + it.method.apply { + val freeRegister = getInstruction(blockStartIndex).registerA - val patternMatch = rollingNumberTextViewAnimationUpdateFingerprint.patternMatch!! - val blockStartIndex = patternMatch.startIndex - val blockEndIndex = patternMatch.endIndex + 1 - rollingNumberTextViewAnimationUpdateFingerprint.method.apply { - val freeRegister = getInstruction(blockStartIndex).registerA + // ReturnYouTubeDislike also makes changes to this same method, + // and must add control flow label to a noop instruction to + // ensure RYD patch adds its changes after the control flow label. + addInstructions(blockEndIndex, "nop") - // ReturnYouTubeDislike also makes changes to this same method, - // and must add control flow label to a noop instruction to - // ensure RYD patch adds its changes after the control flow label. - addInstructions(blockEndIndex, "nop") - - addInstructionsWithLabels( - blockStartIndex, - """ + addInstructionsWithLabels( + blockStartIndex, + """ invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableRollingNumberAnimations()Z move-result v$freeRegister if-nez v$freeRegister, :disable_animations """, - ExternalLabel("disable_animations", getInstruction(blockEndIndex)), - ) + ExternalLabel("disable_animations", getInstruction(blockEndIndex)), + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt deleted file mode 100644 index edf7390cef..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.patches.youtube.layout.hide.seekbar - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.youtube.interaction.seekbar.hideSeekbarPatch - -@Deprecated("Patch was moved to app.revanced.patches.youtube.interaction.seekbar") -val hideSeekbarPatch = bytecodePatch { - dependsOn( - hideSeekbarPatch - ) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt index cc883425ba..7a94fe4623 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt @@ -1,11 +1,15 @@ package app.revanced.patches.youtube.layout.hide.shorts import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val legacyRenderBottomNavigationBarParentFingerprint = fingerprint { +internal val legacyRenderBottomNavigationBarParentFingerprint by fingerprint { parameters( "I", "I", @@ -14,18 +18,24 @@ internal val legacyRenderBottomNavigationBarParentFingerprint = fingerprint { "J", "L", ) - strings("aa") + instructions( + string("aa") + ) } -internal val shortsBottomBarContainerFingerprint = fingerprint { +internal val shortsBottomBarContainerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/view/View;", "Landroid/os/Bundle;") - strings("r_pfvc") - literal { bottomBarContainer } + instructions( + string("r_pfvc"), + resourceLiteral("id", "bottom_bar_container"), + methodCall(name = "getHeight"), + opcode(Opcode.MOVE_RESULT) + ) } -internal val renderBottomNavigationBarFingerprint = fingerprint { +internal val renderBottomNavigationBarFingerprint by fingerprint { returns("V") parameters("Ljava/lang/String;") opcodes( @@ -46,7 +56,7 @@ internal val renderBottomNavigationBarFingerprint = fingerprint { * Identical to [legacyRenderBottomNavigationBarParentFingerprint] * except this has an extra parameter. */ -internal val renderBottomNavigationBarParentFingerprint = fingerprint { +internal val renderBottomNavigationBarParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters( "I", @@ -57,10 +67,12 @@ internal val renderBottomNavigationBarParentFingerprint = fingerprint { "Ljava/lang/String;", "L", ) - strings("aa") + instructions( + string("aa") + ) } -internal val setPivotBarVisibilityFingerprint = fingerprint { +internal val setPivotBarVisibilityFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") parameters("Z") @@ -70,25 +82,27 @@ internal val setPivotBarVisibilityFingerprint = fingerprint { ) } -internal val setPivotBarVisibilityParentFingerprint = fingerprint { +internal val setPivotBarVisibilityParentFingerprint by fingerprint { parameters("Z") - strings("FEnotifications_inbox") + instructions( + string("FEnotifications_inbox") + ) } -internal val shortsExperimentalPlayerFeatureFlagFingerprint = fingerprint { +internal val shortsExperimentalPlayerFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { - 45677719L - } + instructions( + literal(45677719L) + ) } -internal val renderNextUIFeatureFlagFingerprint = fingerprint { +internal val renderNextUIFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { - 45649743L - } + instructions( + literal(45649743L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt index 5cb8bb954e..9e1c04d0ad 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt @@ -8,9 +8,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch @@ -26,15 +25,10 @@ import app.revanced.util.findElementByAttributeValueOrThrow import app.revanced.util.forEachLiteralValueInstruction import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstLiteralInstruction import app.revanced.util.returnLate import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal var bottomBarContainer = -1L - private set -internal var reelPlayerRightPivotV2Size = -1L - private set +import com.google.common.primitives.Shorts internal val hideShortsAppShortcutOption = booleanOption( key = "hideShortsAppShortcut", @@ -140,16 +134,6 @@ private val hideShortsComponentsResourcePatch = resourcePatch { shortsItem.parentNode.removeChild(shortsItem) } } - - bottomBarContainer = resourceMappings[ - "id", - "bottom_bar_container", - ] - - reelPlayerRightPivotV2Size = resourceMappings[ - "dimen", - "reel_player_right_pivot_v2_size", - ] } } @@ -186,7 +170,7 @@ val hideShortsComponentsPatch = bytecodePatch( addLithoFilter(FILTER_CLASS_DESCRIPTOR) forEachLiteralValueInstruction( - reelPlayerRightPivotV2Size, + getResourceId("dimen", "reel_player_right_pivot_v2_size") ) { literalInstructionIndex -> val targetIndex = indexOfFirstInstructionOrThrow(literalInstructionIndex) { getReference()?.name == "getDimensionPixelSize" @@ -212,7 +196,7 @@ val hideShortsComponentsPatch = bytecodePatch( setPivotBarVisibilityParentFingerprint.originalClassDef, ).let { result -> result.method.apply { - val insertIndex = result.patternMatch!!.endIndex + val insertIndex = result.instructionMatches.last().index val viewRegister = getInstruction(insertIndex - 1).registerA addInstruction( insertIndex, @@ -235,26 +219,24 @@ val hideShortsComponentsPatch = bytecodePatch( ) // Hide the bottom bar container of the Shorts player. - shortsBottomBarContainerFingerprint.method.apply { - val resourceIndex = indexOfFirstLiteralInstruction(bottomBarContainer) - - val targetIndex = indexOfFirstInstructionOrThrow(resourceIndex) { - getReference()?.name == "getHeight" - } + 1 - - val heightRegister = getInstruction(targetIndex).registerA - - addInstructions( - targetIndex + 1, - """ - invoke-static { v$heightRegister }, $FILTER_CLASS_DESCRIPTOR->getNavigationBarHeight(I)I - move-result v$heightRegister - """ - ) + shortsBottomBarContainerFingerprint.let { + it.method.apply { + val targetIndex = it.instructionMatches.last().index + val heightRegister = getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, + """ + invoke-static { v$heightRegister }, $FILTER_CLASS_DESCRIPTOR->getNavigationBarHeight(I)I + move-result v$heightRegister + """ + ) + } } // endregion + // region Disable experimental Shorts flags. // Flags might be present in earlier targets, but they are not found in 19.47.53. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt deleted file mode 100644 index 388aee7ad6..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.hide.suggestedvideoendscreen - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.youtube.layout.hide.endscreensuggestion.hideEndScreenSuggestedVideoPatch - -@Deprecated("Use 'Hide suggested video end screen' instead.") -val disableSuggestedVideoEndScreenPatch = bytecodePatch { - dependsOn(hideEndScreenSuggestedVideoPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/Fingerprints.kt index 1f1876dc30..4e4526f7fa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/Fingerprints.kt @@ -1,16 +1,32 @@ package app.revanced.patches.youtube.layout.hide.time +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val timeCounterFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) +internal val timeCounterFingerprint by fingerprint { returns("V") + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() - opcodes( - Opcode.SUB_LONG_2ADDR, - Opcode.IGET_WIDE, - Opcode.SUB_LONG_2ADDR + instructions( + opcode(Opcode.SUB_LONG_2ADDR), + methodCall( + opcode = Opcode.INVOKE_STATIC, + returnType = "Ljava/lang/CharSequence;", + maxAfter = 0 + ), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), + fieldAccess(opcode = Opcode.IGET_WIDE, type = "J", maxAfter = 0), + fieldAccess(opcode = Opcode.IGET_WIDE, type = "J", maxAfter = 0), + opcode(Opcode.SUB_LONG_2ADDR, maxAfter = 0), + + methodCall( + opcode = Opcode.INVOKE_STATIC, + returnType = "Ljava/lang/CharSequence;", + maxAfter = 5 + ) ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt index 04432a1145..9c84f636ec 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt @@ -9,6 +9,8 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch +private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/HideTimestampPatch;" + val hideTimestampPatch = bytecodePatch( name = "Hide timestamp", description = "Adds an option to hide the timestamp in the bottom left of the video player.", @@ -39,13 +41,13 @@ val hideTimestampPatch = bytecodePatch( timeCounterFingerprint.method.addInstructionsWithLabels( 0, """ - invoke-static { }, Lapp/revanced/extension/youtube/patches/HideTimestampPatch;->hideTimestamp()Z + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->hideTimestamp()Z move-result v0 if-eqz v0, :hide_time return-void :hide_time nop - """, + """ ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt index 8c139aee4f..65452bedeb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt @@ -2,23 +2,57 @@ package app.revanced.patches.youtube.layout.miniplayer +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val miniplayerDimensionsCalculatorParentFingerprint = fingerprint { +internal const val MINIPLAYER_MODERN_FEATURE_KEY = 45622882L +// In later targets this feature flag does nothing and is dead code. +internal const val MINIPLAYER_MODERN_FEATURE_LEGACY_KEY = 45630429L +internal const val MINIPLAYER_DOUBLE_TAP_FEATURE_KEY = 45628823L +internal const val MINIPLAYER_DRAG_DROP_FEATURE_KEY = 45628752L +internal const val MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY = 45658112L +internal const val MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY = 45652224L +internal const val MINIPLAYER_INITIAL_SIZE_FEATURE_KEY = 45640023L +internal const val MINIPLAYER_DISABLED_FEATURE_KEY = 45657015L +internal const val MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY = 45644360L + +internal val miniplayerModernConstructorFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) + instructions( + literal(45623000L) // Magic number found in the constructor. + ) +} + +internal val miniplayerDimensionsCalculatorParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") - literal { floatyBarButtonTopMargin } + instructions( + resourceLiteral("dimen", "floaty_bar_button_top_margin") + ) +} + + +internal val miniplayerModernViewParentFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Ljava/lang/String;") + parameters() + instructions( + string("player_overlay_modern_mini_player_controls") + ) } /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ -internal val miniplayerModernAddViewListenerFingerprint = fingerprint { +internal val miniplayerModernAddViewListenerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/view/View;") @@ -27,121 +61,120 @@ internal val miniplayerModernAddViewListenerFingerprint = fingerprint { /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ - -internal val miniplayerModernCloseButtonFingerprint = fingerprint { +internal val miniplayerModernCloseButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { modernMiniplayerClose } -} - -internal const val MINIPLAYER_MODERN_FEATURE_KEY = 45622882L -// In later targets this feature flag does nothing and is dead code. -internal const val MINIPLAYER_MODERN_FEATURE_LEGACY_KEY = 45630429L -internal const val MINIPLAYER_DOUBLE_TAP_FEATURE_KEY = 45628823L -internal const val MINIPLAYER_DRAG_DROP_FEATURE_KEY = 45628752L -internal const val MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY = 45658112L -internal const val MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY = 45652224L -internal const val MINIPLAYER_INITIAL_SIZE_FEATURE_KEY = 45640023L -internal const val MINIPLAYER_DISABLED_FEATURE_KEY = 45657015L - -internal val miniplayerModernConstructorFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - parameters("L") - literal { 45623000L } -} - -internal val miniplayerOnCloseHandlerFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Z") - literal { MINIPLAYER_DISABLED_FEATURE_KEY } + instructions( + resourceLiteral("id", "modern_miniplayer_close"), + checkCast("Landroid/widget/ImageView;") + ) } /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ -internal val miniplayerModernExpandButtonFingerprint = fingerprint { +internal val miniplayerModernExpandButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { modernMiniplayerExpand } + instructions( + resourceLiteral("id", "modern_miniplayer_expand"), + checkCast("Landroid/widget/ImageView;") + ) } /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ -internal val miniplayerModernExpandCloseDrawablesFingerprint = fingerprint { +internal val miniplayerModernExpandCloseDrawablesFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") - literal { ytOutlinePictureInPictureWhite24 } + instructions( + literal(ytOutlinePictureInPictureWhite24) + ) } /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ -internal val miniplayerModernForwardButtonFingerprint = fingerprint { +internal val miniplayerModernForwardButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { modernMiniplayerForwardButton } + instructions( + resourceLiteral("id", "modern_miniplayer_forward_button"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 5) + ) } -/** - * Matches using the class found in [miniplayerModernViewParentFingerprint]. - */ -internal val miniplayerModernOverlayViewFingerprint = fingerprint { +internal val miniplayerModernOverlayViewFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() - literal { scrimOverlay } + instructions( + resourceLiteral("id", "scrim_overlay"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 5) + ) } /** * Matches using the class found in [miniplayerModernViewParentFingerprint]. */ -internal val miniplayerModernRewindButtonFingerprint = fingerprint { +internal val miniplayerModernRewindButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { modernMiniplayerRewindButton } -} - -internal val miniplayerModernViewParentFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Ljava/lang/String;") - parameters() - strings("player_overlay_modern_mini_player_controls") + instructions( + resourceLiteral("id", "modern_miniplayer_rewind_button"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 5) + ) } -internal val miniplayerModernActionButtonFingerprint = fingerprint { +/** + * Matches using the class found in [miniplayerModernViewParentFingerprint]. + */ +internal val miniplayerModernActionButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { modernMiniPlayerOverlayActionButton } + instructions( + resourceLiteral("id", "modern_miniplayer_overlay_action_button"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 5) + ) } -internal val miniplayerMinimumSizeFingerprint = fingerprint { +internal val miniplayerMinimumSizeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - custom { method, _ -> - method.containsLiteralInstruction(192) && - method.containsLiteralInstruction(128) && - method.containsLiteralInstruction(miniplayerMaxSize) - } + instructions( + resourceLiteral("dimen", "miniplayer_max_size"), + literal(192), // Default miniplayer width constant. + literal(128) // Default miniplayer height constant. + ) } -internal val miniplayerOverrideFingerprint = fingerprint { +internal val miniplayerOverrideFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") - strings("appName") + instructions( + string("appName"), + methodCall( + parameters = listOf("Landroid/content/Context;"), + returnType = "Z", + maxAfter = 10 + ) + ) } -internal val miniplayerOverrideNoContextFingerprint = fingerprint { +internal val miniplayerOverrideNoContextFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("Z") - opcodes(Opcode.IGET_BOOLEAN) // Anchor to insert the instruction. + instructions( + opcode(Opcode.IGET_BOOLEAN) // Anchor to insert the instruction. + ) } -internal val miniplayerResponseModelSizeCheckFingerprint = fingerprint { +internal val miniplayerResponseModelSizeCheckFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("Ljava/lang/Object;", "Ljava/lang/Object;") @@ -155,10 +188,18 @@ internal val miniplayerResponseModelSizeCheckFingerprint = fingerprint { ) } +internal val miniplayerOnCloseHandlerFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + instructions( + literal(MINIPLAYER_DISABLED_FEATURE_KEY) + ) +} + internal const val YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME = "Lcom/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout;" -internal val playerOverlaysLayoutFingerprint = fingerprint { +internal val playerOverlaysLayoutFingerprint by fingerprint { custom { method, _ -> method.definingClass == YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt index 4d33823e42..2b98bc53bc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt @@ -13,9 +13,8 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.* import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.* @@ -26,39 +25,17 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction 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 -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.TypeReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter -internal var floatyBarButtonTopMargin = -1L - private set - // Only available in 19.15 and upwards. internal var ytOutlineXWhite24 = -1L private set internal var ytOutlinePictureInPictureWhite24 = -1L private set -internal var scrimOverlay = -1L - private set -internal var modernMiniplayerClose = -1L - private set -internal var modernMiniplayerExpand = -1L - private set -internal var modernMiniplayerRewindButton = -1L - private set -internal var modernMiniplayerForwardButton = -1L - private set -internal var modernMiniPlayerOverlayActionButton = -1L - private set -internal var playerOverlays = -1L - private set -internal var miniplayerMaxSize = -1L - private set private val miniplayerResourcePatch = resourcePatch { dependsOn( @@ -67,72 +44,24 @@ private val miniplayerResourcePatch = resourcePatch { ) execute { - floatyBarButtonTopMargin = resourceMappings[ - "dimen", - "floaty_bar_button_top_margin", - ] - - scrimOverlay = resourceMappings[ - "id", - "scrim_overlay", - ] - - playerOverlays = resourceMappings[ - "layout", - "player_overlays", - ] - - - modernMiniplayerClose = resourceMappings[ - "id", - "modern_miniplayer_close", - ] - - modernMiniplayerExpand = resourceMappings[ - "id", - "modern_miniplayer_expand", - ] - - modernMiniplayerRewindButton = resourceMappings[ - "id", - "modern_miniplayer_rewind_button", - ] - - modernMiniplayerForwardButton = resourceMappings[ - "id", - "modern_miniplayer_forward_button", - ] - - modernMiniPlayerOverlayActionButton = resourceMappings[ - "id", - "modern_miniplayer_overlay_action_button" - ] - // Resource id is not used during patching, but is used by extension. // Verify the resource is present while patching. - resourceMappings[ + getResourceId( "id", "modern_miniplayer_subtitle_text", - ] + ) // Only required for exactly 19.16 if (!is_19_17_or_greater) { - ytOutlinePictureInPictureWhite24 = resourceMappings[ + ytOutlinePictureInPictureWhite24 = getResourceId( "drawable", "yt_outline_picture_in_picture_white_24", - ] + ) - ytOutlineXWhite24 = resourceMappings[ + ytOutlineXWhite24 = getResourceId( "drawable", "yt_outline_x_white_24", - ] - } - - if (is_19_26_or_greater) { - miniplayerMaxSize = resourceMappings[ - "dimen", - "miniplayer_max_size", - ] + ) } } } @@ -166,6 +95,7 @@ val miniplayerPatch = bytecodePatch( val preferences = mutableSetOf() + preferences += if (is_20_03_or_greater) { ListPreference("revanced_miniplayer_type") @@ -298,24 +228,6 @@ val miniplayerPatch = bytecodePatch( ) } - fun MutableMethod.hookInflatedView( - literalValue: Long, - hookedClassType: String, - extensionMethodName: String, - ) { - val imageViewIndex = indexOfFirstInstructionOrThrow( - indexOfFirstLiteralInstructionOrThrow(literalValue), - ) { - opcode == Opcode.CHECK_CAST && getReference()?.type == hookedClassType - } - - val register = getInstruction(imageViewIndex).registerA - addInstruction( - imageViewIndex + 1, - "invoke-static { v$register }, $extensionMethodName", - ) - } - // region Enable tablet miniplayer. miniplayerOverrideNoContextFingerprint.match( @@ -327,18 +239,15 @@ val miniplayerPatch = bytecodePatch( // endregion // region Legacy tablet miniplayer hooks. - val appNameStringIndex = miniplayerOverrideFingerprint.let { - it.method.indexOfFirstInstructionOrThrow(it.stringMatches!!.first().index) { - val reference = getReference() - reference?.parameterTypes?.firstOrNull() == "Landroid/content/Context;" + miniplayerOverrideFingerprint.let { + val appNameStringIndex = it.instructionMatches.last().index + navigate(it.originalMethod).to(appNameStringIndex).stop().apply { + findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) } } } - navigate(miniplayerOverrideFingerprint.originalMethod).to(appNameStringIndex).stop().apply { - findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) } - } miniplayerResponseModelSizeCheckFingerprint.let { - it.method.insertLegacyTabletMiniplayerOverride(it.patternMatch!!.endIndex) + it.method.insertLegacyTabletMiniplayerOverride(it.instructionMatches.last().index) } // endregion @@ -389,7 +298,6 @@ val miniplayerPatch = bytecodePatch( MINIPLAYER_INITIAL_SIZE_FEATURE_KEY, ) val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.LONG_TO_INT) - val register = getInstruction(targetIndex).registerA addInstructions( @@ -402,16 +310,16 @@ val miniplayerPatch = bytecodePatch( } // Override a minimum size constant. - miniplayerMinimumSizeFingerprint.method.apply { - val index = indexOfFirstInstructionOrThrow { - opcode == Opcode.CONST_16 && (this as NarrowLiteralInstruction).narrowLiteral == 192 + miniplayerMinimumSizeFingerprint.let { + it.method.apply { + val index = it.instructionMatches[1].index + val register = getInstruction(index).registerA + + // Smaller sizes can be used, but the miniplayer will always start in size 170 if set any smaller. + // The 170 initial limit probably could be patched to allow even smaller initial sizes, + // but 170 is already half the horizontal space and smaller does not seem useful. + replaceInstruction(index, "const/16 v$register, 170") } - val register = getInstruction(index).registerA - - // Smaller sizes can be used, but the miniplayer will always start in size 170 if set any smaller. - // The 170 initial limit probably could be patched to allow even smaller initial sizes, - // but 170 is already half the horizontal space and smaller does not seem useful. - replaceInstruction(index, "const/16 v$register, 170") } } @@ -432,6 +340,11 @@ val miniplayerPatch = bytecodePatch( MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY, "getHorizontalDrag", ) + + miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride( + MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY, + "getMaximizeAnimation", + ) } // endregion @@ -439,7 +352,7 @@ val miniplayerPatch = bytecodePatch( // region Fix 19.16 using mixed up drawables for tablet modern. // YT fixed this mistake in 19.17. // Fix this, by swapping the drawable resource values with each other. - if (ytOutlinePictureInPictureWhite24 >= 0) { + if (!is_19_17_or_greater) { miniplayerModernExpandCloseDrawablesFingerprint.match( miniplayerModernViewParentFingerprint.originalClassDef, ).method.apply { @@ -460,55 +373,22 @@ val miniplayerPatch = bytecodePatch( // region Add hooks to hide modern miniplayer buttons. listOf( - Triple( - miniplayerModernExpandButtonFingerprint, - modernMiniplayerExpand, - "hideMiniplayerExpandClose", - ), - Triple( - miniplayerModernCloseButtonFingerprint, - modernMiniplayerClose, - "hideMiniplayerExpandClose", - ), - Triple( - miniplayerModernActionButtonFingerprint, - modernMiniPlayerOverlayActionButton, - "hideMiniplayerActionButton" - ), - Triple( - miniplayerModernRewindButtonFingerprint, - modernMiniplayerRewindButton, - "hideMiniplayerRewindForward", - ), - Triple( - miniplayerModernForwardButtonFingerprint, - modernMiniplayerForwardButton, - "hideMiniplayerRewindForward", - ), - Triple( - miniplayerModernOverlayViewFingerprint, - scrimOverlay, - "adjustMiniplayerOpacity", - ), - ).forEach { (fingerprint, literalValue, methodName) -> + miniplayerModernExpandButtonFingerprint to "hideMiniplayerExpandClose", + miniplayerModernCloseButtonFingerprint to "hideMiniplayerExpandClose", + miniplayerModernActionButtonFingerprint to "hideMiniplayerActionButton", + miniplayerModernRewindButtonFingerprint to "hideMiniplayerRewindForward", + miniplayerModernForwardButtonFingerprint to "hideMiniplayerRewindForward", + miniplayerModernOverlayViewFingerprint to "adjustMiniplayerOpacity" + ).forEach { (fingerprint, methodName) -> fingerprint.match( - miniplayerModernViewParentFingerprint.originalClassDef + miniplayerModernViewParentFingerprint.classDef, ).method.apply { - val literalIndex = indexOfFirstLiteralInstructionOrThrow(literalValue) - val checkCastIndex = indexOfFirstInstruction(literalIndex) { - opcode == Opcode.CHECK_CAST && - getReference()?.type == "Landroid/widget/ImageView;" - } - val viewIndex = if (checkCastIndex >= 0) { - checkCastIndex - } else { - indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT) - } - val viewRegister = getInstruction(viewIndex).registerA + val index = fingerprint.instructionMatches.last().index + val register = getInstruction(index).registerA addInstruction( - viewIndex + 1, - "invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V" + index + 1, + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V", ) } } @@ -551,10 +431,10 @@ val miniplayerPatch = bytecodePatch( ).toMutable().apply { addInstructions( """ - invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V - invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V - return-void - """ + invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V + invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V + return-void + """ ) } ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/Fingerprints.kt index 0c31cc83bd..7ac0ce2a11 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/Fingerprints.kt @@ -3,7 +3,7 @@ package app.revanced.patches.youtube.layout.panels.popup import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val engagementPanelControllerFingerprint = fingerprint { +internal val engagementPanelControllerFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("L") strings( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt deleted file mode 100644 index 5c20556a85..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.youtube.layout.player.background - -import app.revanced.patcher.patch.resourcePatch -import app.revanced.patches.youtube.layout.buttons.overlay.hidePlayerOverlayButtonsPatch - -@Suppress("unused") -@Deprecated("Functionality added to hidePlayerOverlayButtonsPatch", ReplaceWith("hidePlayerOverlayButtonsPatch")) -val playerControlsBackgroundPatch = resourcePatch( - description = "Removes the dark background surrounding the video player control buttons.", -) { - dependsOn(hidePlayerOverlayButtonsPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt index a8aef37341..f5783b80c9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt @@ -1,21 +1,49 @@ package app.revanced.patches.youtube.layout.player.fullscreen import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.opcode import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal const val OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG = 45666112L +/** + * 19.46+ + */ +internal val openVideosFullscreenPortraitFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("V") + parameters("L", "Lj\$/util/Optional;") + instructions( + opcode(Opcode.MOVE_RESULT), // Conditional check to modify. + // Open videos fullscreen portrait feature flag. + literal(45666112L, maxAfter = 5), // Cannot be more than 5. + opcode(Opcode.MOVE_RESULT, maxAfter = 10), + ) +} -internal val openVideosFullscreenPortraitFingerprint = fingerprint { +/** + * Pre 19.46. + */ +internal val openVideosFullscreenPortraitLegacyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "Lj\$/util/Optional;") - literal { - OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG - } + opcodes( + Opcode.GOTO, + Opcode.SGET_OBJECT, + Opcode.GOTO, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQ, + Opcode.IF_EQ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT // Conditional check to modify. + ) } -internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint { +internal val openVideosFullscreenHookPatchExtensionFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Z") parameters() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreen.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreen.kt deleted file mode 100644 index 89311b08c0..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreen.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.player.fullscreen - -import app.revanced.patcher.patch.bytecodePatch - -@Suppress("unused") -@Deprecated("Renamed to openVideosFullscreenPatch", ReplaceWith("openVideosFullscreenPatch")) -val openVideosFullscreen = bytecodePatch{ - dependsOn(openVideosFullscreenPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt index 76086c0e48..79253d46b6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt @@ -1,11 +1,15 @@ package app.revanced.patches.youtube.layout.player.fullscreen +import app.revanced.patcher.Fingerprint +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.youtube.layout.shortsplayer.openShortsInRegularPlayerPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.util.insertLiteralOverride +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch;" @@ -20,13 +24,40 @@ internal val openVideosFullscreenHookPatch = bytecodePatch { ) execute { - if (!is_19_46_or_greater) { - return@execute + var fingerprint: Fingerprint + var insertIndex: Int + + if (is_19_46_or_greater) { + fingerprint = openVideosFullscreenPortraitFingerprint + insertIndex = fingerprint.instructionMatches.first().index + + openVideosFullscreenPortraitFingerprint.let { + // Remove A/B feature call that forces what this patch already does. + // Cannot use the A/B flag to accomplish the same goal because 19.50+ + // Shorts fullscreen regular player does not use fullscreen + // if the player is minimized and it must be forced using other conditional check. + it.method.insertLiteralOverride( + it.instructionMatches.last().index, + false + ) + } + } else { + fingerprint = openVideosFullscreenPortraitLegacyFingerprint + insertIndex = fingerprint.instructionMatches.last().index } - openVideosFullscreenPortraitFingerprint.method.insertLiteralOverride( - OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z" - ) + fingerprint.let { + it.method.apply { + val register = getInstruction(insertIndex).registerA + + addInstructions( + insertIndex + 1, + """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->doNotOpenVideoFullscreenPortrait(Z)Z + move-result v$register + """ + ) + } + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatch.kt index 0735dbb1cd..e8485d5b98 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatch.kt @@ -1,12 +1,9 @@ package app.revanced.patches.youtube.layout.player.fullscreen -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.SwitchPreference -import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater -import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.returnEarly @@ -20,11 +17,16 @@ val openVideosFullscreenPatch = bytecodePatch( openVideosFullscreenHookPatch, settingsPatch, addResourcesPatch, - versionCheckPatch ) compatibleWith( "com.google.android.youtube"( + "18.38.44", + "18.49.37", + "19.16.39", + "19.25.37", + "19.34.42", + "19.43.41", "19.47.53", "20.07.39", "20.12.46", @@ -32,10 +34,6 @@ val openVideosFullscreenPatch = bytecodePatch( ) execute { - if (!is_19_46_or_greater) { - throw PatchException("'Open videos fullscreen' requires 19.46.42 or greater") - } - addResources("youtube", "layout.player.fullscreen.openVideosFullscreen") PreferenceScreen.PLAYER.addPreferences( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt index 3f0bb75514..8c0f29b646 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt @@ -6,9 +6,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.InputType import app.revanced.patches.shared.misc.settings.preference.TextPreference import app.revanced.patches.youtube.misc.settings.PreferenceScreen @@ -33,10 +32,10 @@ private val customPlayerOverlayOpacityResourcePatch = resourcePatch { TextPreference("revanced_player_overlay_opacity", inputType = InputType.NUMBER), ) - scrimOverlayId = resourceMappings[ + scrimOverlayId = getResourceId( "id", "scrim_overlay", - ] + ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt index 7269868402..b2bfd80aae 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val createPlayerOverviewFingerprint = fingerprint { +internal val createPlayerOverviewFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt index 54fda75c85..e87999f686 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt @@ -1,26 +1,33 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val dislikeFingerprint = fingerprint { +internal val dislikeFingerprint by fingerprint { returns("V") - strings("like/dislike") + instructions( + string("like/dislike") + ) } -internal val likeFingerprint = fingerprint { +internal val likeFingerprint by fingerprint { returns("V") - strings("like/like") + instructions( + string("like/like") + ) } -internal val removeLikeFingerprint = fingerprint { +internal val removeLikeFingerprint by fingerprint { returns("V") - strings("like/removelike") + instructions( + string("like/removelike") + ) } -internal val rollingNumberMeasureAnimatedTextFingerprint = fingerprint { +internal val rollingNumberMeasureAnimatedTextFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Lj\$/util/Optional;") parameters("L", "Ljava/lang/String;", "L") @@ -41,7 +48,7 @@ internal val rollingNumberMeasureAnimatedTextFingerprint = fingerprint { /** * Matches to class found in [rollingNumberMeasureStaticLabelParentFingerprint]. */ -internal val rollingNumberMeasureStaticLabelFingerprint = fingerprint { +internal val rollingNumberMeasureStaticLabelFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("F") parameters("Ljava/lang/String;") @@ -53,14 +60,16 @@ internal val rollingNumberMeasureStaticLabelFingerprint = fingerprint { ) } -internal val rollingNumberMeasureStaticLabelParentFingerprint = fingerprint { +internal val rollingNumberMeasureStaticLabelParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters() - strings("RollingNumberFontProperties{paint=") + instructions( + string("RollingNumberFontProperties{paint=") + ) } -internal val rollingNumberSetterFingerprint = fingerprint { +internal val rollingNumberSetterFingerprint by fingerprint { opcodes( Opcode.INVOKE_DIRECT, Opcode.IGET_OBJECT, @@ -69,7 +78,7 @@ internal val rollingNumberSetterFingerprint = fingerprint { strings("RollingNumberType required properties missing! Need") } -internal val rollingNumberTextViewFingerprint = fingerprint { +internal val rollingNumberTextViewFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "F", "F") @@ -87,15 +96,19 @@ internal val rollingNumberTextViewFingerprint = fingerprint { } } -internal val textComponentConstructorFingerprint = fingerprint { +internal val textComponentConstructorFingerprint by fingerprint { accessFlags(AccessFlags.CONSTRUCTOR, AccessFlags.PRIVATE) - strings("TextComponent") + instructions( + string("TextComponent") + ) } -internal val textComponentDataFingerprint = fingerprint { +internal val textComponentDataFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters("L", "L") - strings("text") + instructions( + string("text") + ) custom { _, classDef -> classDef.fields.find { it.type == "Ljava/util/BitSet;" } != null } @@ -104,18 +117,20 @@ internal val textComponentDataFingerprint = fingerprint { /** * Matches against the same class found in [textComponentConstructorFingerprint]. */ -internal val textComponentLookupFingerprint = fingerprint { +internal val textComponentLookupFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returns("L") parameters("L") - strings("…") + instructions( + string("…") + ) } -internal const val LITHO_NEW_TEXT_COMPONENT_FEATURE_FLAG = 45675738L - -internal val textComponentFeatureFlagFingerprint = fingerprint { +internal val textComponentFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.FINAL) returns("Z") parameters() - literal { LITHO_NEW_TEXT_COMPONENT_FEATURE_FLAG } -} + instructions ( + literal(45675738L) + ) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index e804385370..b196eb34a5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -103,7 +103,7 @@ val returnYouTubeDislikePatch = bytecodePatch( // region Hook like/dislike/remove like button clicks to send votes to the API. - mapOf( + arrayOf( likeFingerprint to Vote.LIKE, dislikeFingerprint to Vote.DISLIKE, removeLikeFingerprint to Vote.REMOVE_LIKE, @@ -121,10 +121,10 @@ val returnYouTubeDislikePatch = bytecodePatch( // region Hook code for creation and cached lookup of text Spans. - // Alternatively the hook can be made at tht it fails to update the Span when the user dislikes, - // // since the underlying (likes only) tee creation of Spans in TextComponentSpec, - // And it works in all situations excepxt did not change. + // Alternatively the hook can be made in the creation of Spans in TextComponentSpec. + // And it works in all situations except if the likes do not such as disliking. // This hook handles all situations, as it's where the created Spans are stored and later reused. + // Find the field name of the conversion context. val conversionContextField = textComponentConstructorFingerprint.originalClassDef.fields.find { it.type == conversionContextFingerprintToString.originalClassDef.type @@ -136,41 +136,35 @@ val returnYouTubeDislikePatch = bytecodePatch( val textDataClassType = textComponentDataFingerprint.originalClassDef.type val insertIndex: Int - val tempRegister: Int val charSequenceRegister: Int - if (is_19_33_or_greater && !is_20_10_or_greater) { - insertIndex = indexOfFirstInstructionOrThrow { + if (is_19_33_or_greater && !is_20_10_or_greater) { + val index = indexOfFirstInstructionOrThrow { (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) && getReference()?.returnType == textDataClassType } - tempRegister = getInstruction(insertIndex + 1).registerA - - // Find the instruction that sets the span to an instance field. - // The instruction is only a few lines after the creation of the instance. - charSequenceRegister = getInstruction( - indexOfFirstInstructionOrThrow(insertIndex) { - opcode == Opcode.INVOKE_VIRTUAL && + insertIndex = indexOfFirstInstructionOrThrow(index) { + opcode == Opcode.INVOKE_VIRTUAL && getReference()?.parameterTypes?.firstOrNull() == "Ljava/lang/CharSequence;" - }, - ).registerD + } + + charSequenceRegister = getInstruction(insertIndex).registerD } else { insertIndex = indexOfFirstInstructionOrThrow { opcode == Opcode.NEW_INSTANCE && getReference()?.type == textDataClassType } - tempRegister = getInstruction(insertIndex).registerA - - charSequenceRegister = getInstruction( - indexOfFirstInstructionOrThrow(insertIndex) { - opcode == Opcode.IPUT_OBJECT && + val charSequenceIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.IPUT_OBJECT && getReference()?.type == "Ljava/lang/CharSequence;" - }, - ).registerA + } + charSequenceRegister = getInstruction(charSequenceIndex).registerA } + val tempRegister = findFreeRegister(insertIndex, charSequenceRegister) + addInstructionsAtControlFlowLabel( insertIndex, """ @@ -205,11 +199,9 @@ val returnYouTubeDislikePatch = bytecodePatch( // region Hook rolling numbers. - val dislikesIndex = rollingNumberSetterFingerprint.patternMatch!!.endIndex - rollingNumberSetterFingerprint.method.apply { val insertIndex = 1 - + val dislikesIndex = rollingNumberSetterFingerprint.instructionMatches.last().index val charSequenceInstanceRegister = getInstruction(0).registerA val charSequenceFieldReference = @@ -226,17 +218,16 @@ val returnYouTubeDislikePatch = bytecodePatch( invoke-static {v$conversionContextRegister, v$freeRegister}, $EXTENSION_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String; move-result-object v$freeRegister iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference - """, + """ ) } + // Rolling Number text views use the measured width of the raw string for layout. + // Modify the measure text calculation to include the left drawable separator if needed. rollingNumberMeasureAnimatedTextFingerprint.let { - // Rolling Number text views use the measured width of the raw string for layout. - // Modify the measure text calculation to include the left drawable separator if needed. - val patternMatch = it.patternMatch!! - // Verify the opcodes are at the start of the method. - if (patternMatch.startIndex != 0) throw PatchException("Unexpected opcode location") - val endIndex = patternMatch.endIndex + // Additional check to verify the opcodes are at the start of the method + if (it.instructionMatches.first().index != 0) throw PatchException("Unexpected opcode location") + val endIndex = it.instructionMatches.last().index it.method.apply { val measuredTextWidthRegister = getInstruction(endIndex).registerA @@ -256,7 +247,7 @@ val returnYouTubeDislikePatch = bytecodePatch( rollingNumberMeasureStaticLabelFingerprint.match( rollingNumberMeasureStaticLabelParentFingerprint.originalClassDef, ).let { - val measureTextIndex = it.patternMatch!!.startIndex + 1 + val measureTextIndex = it.instructionMatches.first().index + 1 it.method.apply { val freeRegister = getInstruction(0).registerA @@ -265,7 +256,7 @@ val returnYouTubeDislikePatch = bytecodePatch( """ move-result v$freeRegister invoke-static {p1, v$freeRegister}, $EXTENSION_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - """, + """ ) } } @@ -284,10 +275,8 @@ val returnYouTubeDislikePatch = bytecodePatch( getReference()?.name == "setText" } - val textViewRegister = - getInstruction(setTextIndex).registerC - val textSpanRegister = - getInstruction(setTextIndex).registerD + val textViewRegister = getInstruction(setTextIndex).registerC + val textSpanRegister = getInstruction(setTextIndex).registerD addInstructions( setTextIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/Fingerprints.kt index 2dbff83a23..e70a6b080a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/Fingerprints.kt @@ -1,27 +1,28 @@ package app.revanced.patches.youtube.layout.searchbar import app.revanced.patcher.fingerprint +import app.revanced.patches.shared.misc.mapping.resourceLiteral import app.revanced.patches.youtube.layout.hide.general.yoodlesImageViewFingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags -internal val setWordmarkHeaderFingerprint = fingerprint { +internal val setWordmarkHeaderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/widget/ImageView;") - custom { methodDef, _ -> - methodDef.containsLiteralInstruction(ytPremiumWordmarkHeaderId) && - methodDef.containsLiteralInstruction(ytWordmarkHeaderId) - } + instructions( + resourceLiteral("attr", "ytPremiumWordmarkHeader"), + resourceLiteral("attr", "ytWordmarkHeader") + ) } /** * Matches the same method as [yoodlesImageViewFingerprint]. */ -internal val wideSearchbarLayoutFingerprint = fingerprint { +internal val wideSearchbarLayoutFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") parameters("L", "L") - literal { actionBarRingoId } + instructions( + resourceLiteral("layout", "action_bar_ringo"), + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt index cdfcbfc1eb..765cd8df5a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt @@ -3,12 +3,9 @@ package app.revanced.patches.youtube.layout.searchbar import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen @@ -24,34 +21,6 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/WideSearchbarPatch;" -internal var ytWordmarkHeaderId = -1L - private set -internal var ytPremiumWordmarkHeaderId = -1L - private set -internal var actionBarRingoId = -1L - private set - -private val wideSearchbarResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - ytWordmarkHeaderId = resourceMappings[ - "attr", - "ytWordmarkHeader", - ] - - ytPremiumWordmarkHeaderId = resourceMappings[ - "attr", - "ytPremiumWordmarkHeader", - ] - - actionBarRingoId = resourceMappings[ - "layout", - "action_bar_ringo", - ] - } -} - val wideSearchbarPatch = bytecodePatch( name = "Wide search bar", description = "Adds an option to replace the search icon with a wide search bar. " + @@ -61,7 +30,7 @@ val wideSearchbarPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, - wideSearchbarResourcePatch, + resourceMappingPatch, ) compatibleWith( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt index 25d2918096..052d082571 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt @@ -1,69 +1,76 @@ package app.revanced.patches.youtube.layout.seekbar +import app.revanced.patcher.anyInstruction import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val fullscreenSeekbarThumbnailsFingerprint = fingerprint { +internal val fullscreenSeekbarThumbnailsFingerprint by fingerprint { returns("Z") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters() - literal { 45398577 } + instructions( + literal(45398577) + ) } -internal val playerSeekbarColorFingerprint = fingerprint { +internal val playerSeekbarColorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - custom { method, _ -> - method.containsLiteralInstruction(inlineTimeBarColorizedBarPlayedColorDarkId) && - method.containsLiteralInstruction(inlineTimeBarPlayedNotHighlightedColorId) - } + instructions( + resourceLiteral("color", "inline_time_bar_played_not_highlighted_color"), + resourceLiteral("color", "inline_time_bar_colorized_bar_played_color_dark") + ) } -internal val setSeekbarClickedColorFingerprint = fingerprint { +internal val setSeekbarClickedColorFingerprint by fingerprint { opcodes(Opcode.CONST_HIGH16) strings("YOUTUBE", "PREROLL", "POSTROLL") custom { _, classDef -> - classDef.endsWith("ControlsOverlayStyle;") + classDef.endsWith("/ControlsOverlayStyle;") } } -internal val shortsSeekbarColorFingerprint = fingerprint { +internal val shortsSeekbarColorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - literal { reelTimeBarPlayedColorId } + instructions( + resourceLiteral("color", "reel_time_bar_played_color") + ) } -internal val playerSeekbarHandle1ColorFingerprint = fingerprint { +internal val playerSeekbarHandle1ColorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters("Landroid/content/Context;") - custom { method, _ -> - method.containsLiteralInstruction(ytTextSecondaryId) && - method.containsLiteralInstruction(ytStaticBrandRedId) - } + instructions( + resourceLiteral("attr", "ytTextSecondary"), + resourceLiteral("attr", "ytStaticBrandRed"), + ) } -internal val playerSeekbarHandle2ColorFingerprint = fingerprint { +internal val playerSeekbarHandle2ColorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - parameters("Landroid/content/Context;") - custom { method, _ -> - method.containsLiteralInstruction(inlineTimeBarLiveSeekableRangeId) && - method.containsLiteralInstruction(ytStaticBrandRedId) - } + instructions( + resourceLiteral("color", "inline_time_bar_live_seekable_range"), + resourceLiteral("attr", "ytStaticBrandRed"), + ) } - -internal val watchHistoryMenuUseProgressDrawableFingerprint = fingerprint { +internal val watchHistoryMenuUseProgressDrawableFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") - literal { -1712394514 } + instructions( + methodCall("Landroid/widget/ProgressBar;", "setMax"), + opcode(Opcode.MOVE_RESULT), + literal(-1712394514) + ) } -internal val lithoLinearGradientFingerprint = fingerprint { +internal val lithoLinearGradientFingerprint by fingerprint { accessFlags(AccessFlags.STATIC) returns("Landroid/graphics/LinearGradient;") parameters("F", "F", "F", "F", "[I", "[F") @@ -72,76 +79,93 @@ internal val lithoLinearGradientFingerprint = fingerprint { /** * 19.49+ */ -internal val playerLinearGradientFingerprint = fingerprint { +internal val playerLinearGradientFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) parameters("I", "I", "I", "I", "Landroid/content/Context;", "I") returns("Landroid/graphics/LinearGradient;") - opcodes( - Opcode.FILLED_NEW_ARRAY, - Opcode.MOVE_RESULT_OBJECT + instructions( + resourceLiteral("color", "yt_youtube_magenta"), + + opcode(Opcode.FILLED_NEW_ARRAY, maxAfter = 5), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) ) - literal { ytYoutubeMagentaColorId } } /** * 19.25 - 19.47 */ -internal val playerLinearGradientLegacyFingerprint = fingerprint { +internal val playerLinearGradientLegacyFingerprint by fingerprint { returns("V") - opcodes( - Opcode.FILLED_NEW_ARRAY, - Opcode.MOVE_RESULT_OBJECT + instructions( + resourceLiteral("color", "yt_youtube_magenta"), + + opcode(Opcode.FILLED_NEW_ARRAY), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), ) - literal { ytYoutubeMagentaColorId } } internal const val launchScreenLayoutTypeLotteFeatureFlag = 268507948L -internal val launchScreenLayoutTypeFingerprint = fingerprint { +internal val launchScreenLayoutTypeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") + instructions( + literal(launchScreenLayoutTypeLotteFeatureFlag) + ) custom { method, _ -> val firstParameter = method.parameterTypes.firstOrNull() // 19.25 - 19.45 - (firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;" - || firstParameter == "Landroid/app/Activity;") // 19.46+ - && method.containsLiteralInstruction(launchScreenLayoutTypeLotteFeatureFlag) + firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;" + || firstParameter == "Landroid/app/Activity;" // 19.46+ + } +} + +internal val mainActivityOnCreateSplashScreenImageViewFingerprint by fingerprint { + returns("V") + parameters("Landroid/os/Bundle;") + instructions( + methodCall(definingClass = "Landroid/widget/ImageView;", name = "getDrawable"), + opcode(Opcode.CHECK_CAST) + ) + custom { method, classDef -> + method.name == "onCreate" && classDef.endsWith("/MainActivity;") } } internal const val LOTTIE_ANIMATION_VIEW_CLASS_TYPE = "Lcom/airbnb/lottie/LottieAnimationView;" -internal val lottieAnimationViewSetAnimationIntFingerprint = fingerprint { +internal val lottieAnimationViewSetAnimationIntFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("I") returns("V") - custom { methodDef, classDef -> - classDef.type == LOTTIE_ANIMATION_VIEW_CLASS_TYPE && methodDef.indexOfFirstInstruction { - val reference = getReference() - reference?.definingClass == "Lcom/airbnb/lottie/LottieAnimationView;" - && reference.name == "isInEditMode" - } >= 0 + instructions( + methodCall("this", "isInEditMode") + ) + custom { _, classDef -> + classDef.type == LOTTIE_ANIMATION_VIEW_CLASS_TYPE } } -internal val lottieAnimationViewSetAnimationStreamFingerprint = fingerprint { +internal val lottieAnimationViewSetAnimationStreamFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("L") returns("V") - custom { methodDef, classDef -> - classDef.type == LOTTIE_ANIMATION_VIEW_CLASS_TYPE && methodDef.indexOfFirstInstruction { - val reference = getReference() - reference?.definingClass == "Ljava/util/Set;" - && reference.name == "add" - } >= 0 && methodDef.containsLiteralInstruction(0) + instructions( + methodCall("Ljava/util/Set;", "add"), + literal(0) + ) + custom { _, classDef -> + classDef.type == LOTTIE_ANIMATION_VIEW_CLASS_TYPE } } -internal val lottieCompositionFactoryZipFingerprint = fingerprint { +internal val lottieCompositionFactoryZipFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) parameters("Landroid/content/Context;", "Ljava/lang/String;", "Ljava/lang/String;") returns("L") - strings(".zip", ".lottie") + instructions( + string(".zip"), + string(".lottie") + ) } /** @@ -149,11 +173,12 @@ internal val lottieCompositionFactoryZipFingerprint = fingerprint { * * [Original method](https://github.com/airbnb/lottie-android/blob/26ad8bab274eac3f93dccccfa0cafc39f7408d13/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java#L386) */ -internal val lottieCompositionFactoryFromJsonInputStreamFingerprint = fingerprint { +internal val lottieCompositionFactoryFromJsonInputStreamFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) parameters("Ljava/io/InputStream;", "Ljava/lang/String;") returns("L") - literal { 2 } + instructions( + anyInstruction(literal(2), literal(3)) + ) } - diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt index 76fe99b31b..33df126aa3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt @@ -10,9 +10,7 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.youtube.layout.theme.lithoColorHookPatch import app.revanced.patches.youtube.layout.theme.lithoColorOverrideHook import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch @@ -21,7 +19,6 @@ import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch -import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint import app.revanced.util.copyXmlNode import app.revanced.util.findElementByAttributeValueOrThrow @@ -43,56 +40,15 @@ import org.w3c.dom.Element import java.io.ByteArrayInputStream import kotlin.use -internal var reelTimeBarPlayedColorId = -1L - private set -internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L - private set -internal var inlineTimeBarPlayedNotHighlightedColorId = -1L - private set -internal var ytYoutubeMagentaColorId = -1L - private set -internal var ytStaticBrandRedId = -1L - private set -internal var ytTextSecondaryId = -1L - private set -internal var inlineTimeBarLiveSeekableRangeId = -1L - private set - -internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color" +private const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color" private val seekbarColorResourcePatch = resourcePatch { dependsOn( - settingsPatch, resourceMappingPatch, versionCheckPatch, ) execute { - reelTimeBarPlayedColorId = resourceMappings[ - "color", - "reel_time_bar_played_color", - ] - inlineTimeBarColorizedBarPlayedColorDarkId = resourceMappings[ - "color", - "inline_time_bar_colorized_bar_played_color_dark", - ] - inlineTimeBarPlayedNotHighlightedColorId = resourceMappings[ - "color", - "inline_time_bar_played_not_highlighted_color", - ] - ytStaticBrandRedId = resourceMappings[ - "attr", - "ytStaticBrandRed" - ] - ytTextSecondaryId = resourceMappings[ - "attr", - "ytTextSecondary" - ] - inlineTimeBarLiveSeekableRangeId = resourceMappings[ - "color", - "inline_time_bar_live_seekable_range" - ] - // Modify the resume playback drawable and replace the progress bar with a custom drawable. document("res/drawable/resume_playback_progressbar_drawable.xml").use { document -> val layerList = document.getElementsByTagName("layer-list").item(0) as Element @@ -113,15 +69,6 @@ private val seekbarColorResourcePatch = resourcePatch { return@execute } - ytYoutubeMagentaColorId = resourceMappings[ - "color", - "yt_youtube_magenta", - ] - ytStaticBrandRedId = resourceMappings[ - "attr", - "ytStaticBrandRed", - ] - // Add attribute and styles for splash screen custom color. // Using a style is the only way to selectively change just the seekbar fill color. // @@ -223,28 +170,31 @@ val seekbarColorPatch = bytecodePatch( sharedExtensionPatch, lithoColorHookPatch, seekbarColorResourcePatch, + resourceMappingPatch, versionCheckPatch ) execute { - fun MutableMethod.addColorChangeInstructions(resourceId: Long) { + fun MutableMethod.addColorChangeInstructions(index: Int) { insertLiteralOverride( - resourceId, + index, "$EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I" ) } - playerSeekbarColorFingerprint.method.apply { - addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId) - addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId) + playerSeekbarColorFingerprint.let { + it.method.apply { + addColorChangeInstructions(it.instructionMatches.last().index) + addColorChangeInstructions(it.instructionMatches.first().index) + } } - shortsSeekbarColorFingerprint.method.apply { - addColorChangeInstructions(reelTimeBarPlayedColorId) + shortsSeekbarColorFingerprint.let { + it.method.addColorChangeInstructions(it.instructionMatches.first().index) } setSeekbarClickedColorFingerprint.originalMethod.let { - val setColorMethodIndex = setSeekbarClickedColorFingerprint.patternMatch!!.startIndex + 1 + val setColorMethodIndex = setSeekbarClickedColorFingerprint.instructionMatches.first().index + 1 navigate(it).to(setColorMethodIndex).stop().apply { val colorRegister = getInstruction(0).registerA @@ -253,7 +203,7 @@ val seekbarColorPatch = bytecodePatch( """ invoke-static { v$colorRegister }, $EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarClickedColor(I)I move-result v$colorRegister - """, + """ ) } } @@ -270,28 +220,26 @@ val seekbarColorPatch = bytecodePatch( playerSeekbarHandle1ColorFingerprint, playerSeekbarHandle2ColorFingerprint ).forEach { - it.method.addColorChangeInstructions(ytStaticBrandRedId) + it.method.addColorChangeInstructions(it.instructionMatches.last().index) } // If hiding feed seekbar thumbnails, then turn off the cairo gradient // of the watch history menu items as they use the same gradient as the // player and there is no easy way to distinguish which to use a transparent color. if (is_19_34_or_greater) { - watchHistoryMenuUseProgressDrawableFingerprint.method.apply { - val progressIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.definingClass == "Landroid/widget/ProgressBar;" && reference.name == "setMax" - } - val index = indexOfFirstInstructionOrThrow(progressIndex, Opcode.MOVE_RESULT) - val register = getInstruction(index).registerA + watchHistoryMenuUseProgressDrawableFingerprint.let { + it.method.apply { + val index = it.instructionMatches[1].index + val register = getInstruction(index).registerA - addInstructions( - index + 1, - """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z - move-result v$register - """ - ) + addInstructions( + index + 1, + """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z + move-result v$register + """ + ) + } } } @@ -315,7 +263,7 @@ val seekbarColorPatch = bytecodePatch( playerFingerprint.let { it.method.apply { - val index = it.patternMatch!!.endIndex + val index = it.instructionMatches.last().index val register = getInstruction(index).registerA addInstructions( @@ -369,11 +317,12 @@ val seekbarColorPatch = bytecodePatch( ) // Replace the Lottie animation view setAnimation(int) call. - val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name + val setAnimationIntMethodName = + lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name findInstructionIndicesReversedOrThrow { val reference = getReference() - reference?.definingClass == "Lcom/airbnb/lottie/LottieAnimationView;" + reference?.definingClass == LOTTIE_ANIMATION_VIEW_CLASS_TYPE && reference.name == setAnimationIntMethodName }.forEach { index -> val instruction = getInstruction(index) @@ -381,18 +330,18 @@ val seekbarColorPatch = bytecodePatch( replaceInstruction( index, "invoke-static { v${instruction.registerC}, v${instruction.registerD} }, " + - "$EXTENSION_CLASS_DESCRIPTOR->setSplashAnimationLottie" + - "(Lcom/airbnb/lottie/LottieAnimationView;I)V" + "$EXTENSION_CLASS_DESCRIPTOR->setSplashAnimationLottie" + + "(Lcom/airbnb/lottie/LottieAnimationView;I)V" ) } } - // Add non obfuscated method aliases for `setAnimation(int)` // and `setAnimation(InputStream, String)` so extension code can call them. lottieAnimationViewSetAnimationIntFingerprint.classDef.methods.apply { val addedMethodName = "patch_setAnimation" - val setAnimationIntName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name + val setAnimationIntName = lottieAnimationViewSetAnimationIntFingerprint + .originalMethod.name add(ImmutableMethod( LOTTIE_ANIMATION_VIEW_CLASS_TYPE, @@ -412,9 +361,9 @@ val seekbarColorPatch = bytecodePatch( ) }) - val factoryStreamClass : CharSequence - val factoryStreamName : CharSequence - val factoryStreamReturnType : CharSequence + val factoryStreamClass: CharSequence + val factoryStreamName: CharSequence + val factoryStreamReturnType: CharSequence lottieCompositionFactoryFromJsonInputStreamFingerprint.match( lottieCompositionFactoryZipFingerprint.originalClassDef ).originalMethod.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt index 045d75ca28..c75606b95a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt @@ -1,51 +1,50 @@ package app.revanced.patches.youtube.layout.shortsautoplay +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string 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 val reelEnumConstructorFingerprint = fingerprint { +internal val reelEnumConstructorFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - opcodes(Opcode.RETURN_VOID) - strings( - "REEL_LOOP_BEHAVIOR_UNKNOWN", - "REEL_LOOP_BEHAVIOR_SINGLE_PLAY", - "REEL_LOOP_BEHAVIOR_REPEAT", - "REEL_LOOP_BEHAVIOR_END_SCREEN", + instructions( + string("REEL_LOOP_BEHAVIOR_UNKNOWN"), + string("REEL_LOOP_BEHAVIOR_SINGLE_PLAY"), + string("REEL_LOOP_BEHAVIOR_REPEAT"), + string("REEL_LOOP_BEHAVIOR_END_SCREEN"), + opcode(Opcode.RETURN_VOID) ) } -internal val reelPlaybackRepeatFingerprint = fingerprint { +internal val reelPlaybackRepeatParentFingerprint by fingerprint { returns("V") - parameters("L") - strings("YoutubePlayerState is in throwing an Error.") + parameters("Ljava/lang/String;", "J") + instructions( + string("Reels[%s] Playback Time: %d ms") + ) } -internal val reelPlaybackFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) +/** + * Matches class found in [reelPlaybackRepeatParentFingerprint]. + */ +internal val reelPlaybackRepeatFingerprint by fingerprint { returns("V") - parameters("J") - custom { method, _ -> - indexOfMilliSecondsInstruction(method) >= 0 && - indexOfInitializationInstruction(method) >= 0 - } + parameters("L") + instructions( + methodCall(smali = "Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z") + ) } -private fun indexOfMilliSecondsInstruction(method: Method) = - method.indexOfFirstInstruction { - getReference()?.name == "MILLISECONDS" - } - -internal fun indexOfInitializationInstruction(method: Method) = - method.indexOfFirstInstruction { - val reference = getReference() - opcode == Opcode.INVOKE_DIRECT && - reference?.name == "" && - reference.parameterTypes.size == 3 && - reference.parameterTypes.firstOrNull() == "I" - } +internal val reelPlaybackFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters("J") + returns("V") + instructions( + fieldAccess(definingClass = "Ljava/util/concurrent/TimeUnit;", name = "MILLISECONDS"), + methodCall(name = "", parameters = listOf("I", "L", "L"), maxAfter = 15), + methodCall(opcode = Opcode.INVOKE_VIRTUAL, parameters = listOf("L"), returnType = "I", maxAfter = 5) + ) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt index 9cbffafb19..6755c5ce40 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt @@ -71,23 +71,25 @@ val shortsAutoplayPatch = bytecodePatch( "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V", ) - val reelEnumClass = reelEnumConstructorFingerprint.originalClassDef.type + var reelEnumClass : String - reelEnumConstructorFingerprint.method.apply { - val insertIndex = reelEnumConstructorFingerprint.patternMatch!!.startIndex + reelEnumConstructorFingerprint.let { + reelEnumClass = it.originalClassDef.type - addInstructions( - insertIndex, + it.method.addInstructions( + it.instructionMatches.last().index, """ # Pass the first enum value to extension. # Any enum value of this type will work. sget-object v0, $reelEnumClass->a:$reelEnumClass invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setYTShortsRepeatEnum(Ljava/lang/Enum;)V - """, + """ ) } - - reelPlaybackRepeatFingerprint.method.apply { + + reelPlaybackRepeatFingerprint.match( + reelPlaybackRepeatParentFingerprint.originalClassDef + ).method.apply { // The behavior enums are looked up from an ordinal value to an enum type. findInstructionIndicesReversedOrThrow { val reference = getReference() @@ -102,7 +104,7 @@ val shortsAutoplayPatch = bytecodePatch( """ invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->changeShortsRepeatBehavior(Ljava/lang/Enum;)Ljava/lang/Enum; move-result-object v$register - """, + """ ) } } @@ -111,13 +113,10 @@ val shortsAutoplayPatch = bytecodePatch( // Manually restore the removed 'Autoplay' code. if (is_20_09_or_greater) { // Variable names are only a rough guess of what these methods do. - val userActionMethodIndex = indexOfInitializationInstruction(reelPlaybackFingerprint.method) - val userActionMethodReference = reelPlaybackFingerprint.method - .getInstruction(userActionMethodIndex).reference as MethodReference - val reelSequenceControllerMethodIndex = reelPlaybackFingerprint.method - .indexOfFirstInstructionOrThrow(userActionMethodIndex, Opcode.INVOKE_VIRTUAL) - val reelSequenceControllerMethodReference = reelPlaybackFingerprint.method - .getInstruction(reelSequenceControllerMethodIndex).reference as MethodReference + val userActionMethodReference = reelPlaybackFingerprint.instructionMatches[1] + .getInstruction().reference as MethodReference + val reelSequenceControllerMethodReference = reelPlaybackFingerprint.instructionMatches[2] + .getInstruction().reference as MethodReference reelPlaybackRepeatFingerprint.method.apply { // Find the first call modified by extension code above. @@ -126,7 +125,7 @@ val shortsAutoplayPatch = bytecodePatch( getReference()?.definingClass == EXTENSION_CLASS_DESCRIPTOR } + 1 val enumRegister = getInstruction(extensionReturnResultIndex).registerA - val getReelSequenceControllerIndex = indexOfFirstInstructionOrThrow(extensionReturnResultIndex) { + val getReelSequenceControllerIndex = indexOfFirstInstructionOrThrow { val reference = getReference() opcode == Opcode.IGET_OBJECT && reference?.definingClass == definingClass && diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt index abd7f10ceb..f1d80f1bd5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt @@ -1,25 +1,32 @@ package app.revanced.patches.youtube.layout.shortsplayer import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags /** * Purpose of this method is not clear, and it's only used to identify * the obfuscated name of the videoId() method in PlaybackStartDescriptor. */ -internal val playbackStartFeatureFlagFingerprint = fingerprint { +internal val playbackStartFeatureFlagFingerprint by fingerprint { returns("Z") parameters( "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;", ) - literal { - 45380134L - } + instructions( + methodCall( + definingClass = "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;", + returnType = "Ljava/lang/String;" + ), + literal(45380134L) + ) } // Pre 19.25 -internal val shortsPlaybackIntentLegacyFingerprint = fingerprint { +internal val shortsPlaybackIntentLegacyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters( @@ -30,15 +37,16 @@ internal val shortsPlaybackIntentLegacyFingerprint = fingerprint { "Z", "Ljava/util/Map;" ) - strings( + instructions( + methodCall(returnType = "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"), // None of these strings are unique. - "com.google.android.apps.youtube.app.endpoint.flags", - "ReelWatchFragmentArgs", - "reels_fragment_descriptor" + string("com.google.android.apps.youtube.app.endpoint.flags"), + string("ReelWatchFragmentArgs"), + string("reels_fragment_descriptor") ) } -internal val shortsPlaybackIntentFingerprint = fingerprint { +internal val shortsPlaybackIntentFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returns("V") parameters( @@ -47,18 +55,18 @@ internal val shortsPlaybackIntentFingerprint = fingerprint { "J", "Ljava/lang/String;" ) - strings( + instructions( // None of these strings are unique. - "com.google.android.apps.youtube.app.endpoint.flags", - "ReelWatchFragmentArgs", - "reels_fragment_descriptor" + string("com.google.android.apps.youtube.app.endpoint.flags"), + string("ReelWatchFragmentArgs"), + string("reels_fragment_descriptor") ) } -internal val exitVideoPlayerFingerprint = fingerprint { +internal val exitVideoPlayerFingerprint by fingerprint { returns("V") parameters() - literal { - mdx_drawer_layout_id - } + instructions( + resourceLiteral("id", "mdx_drawer_layout") + ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt index 1b2949c79f..200ca4c802 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt @@ -5,18 +5,14 @@ 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.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.youtube.layout.player.fullscreen.openVideosFullscreenHookPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater -import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch @@ -32,21 +28,6 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch;" -internal var mdx_drawer_layout_id = -1L - private set - -private val openShortsInRegularPlayerResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - mdx_drawer_layout_id = resourceMappings[ - "id", - "mdx_drawer_layout", - ] - - } -} - @Suppress("unused") val openShortsInRegularPlayerPatch = bytecodePatch( name = "Open Shorts in regular player", @@ -59,7 +40,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch( openVideosFullscreenHookPatch, navigationBarHookPatch, versionCheckPatch, - openShortsInRegularPlayerResourcePatch + resourceMappingPatch ) compatibleWith( @@ -76,15 +57,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch( addResources("youtube", "layout.shortsplayer.shortsPlayerTypePatch") PreferenceScreen.SHORTS.addPreferences( - if (is_19_46_or_greater) { - ListPreference("revanced_shorts_player_type") - } else { - ListPreference( - key = "revanced_shorts_player_type", - entriesKey = "revanced_shorts_player_type_legacy_entries", - entryValuesKey = "revanced_shorts_player_type_legacy_entry_values" - ) - } + ListPreference("revanced_shorts_player_type") ) // Activity is used as the context to launch an Intent. @@ -95,14 +68,11 @@ val openShortsInRegularPlayerPatch = bytecodePatch( ) // Find the obfuscated method name for PlaybackStartDescriptor.videoId() - val playbackStartVideoIdMethodName = playbackStartFeatureFlagFingerprint.method.let { - val stringMethodIndex = it.indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.definingClass == "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;" - && reference.returnType == "Ljava/lang/String;" + val playbackStartVideoIdMethodName = playbackStartFeatureFlagFingerprint.let { + val stringMethodIndex = it.instructionMatches.first().index + it.method.let { + navigate(it).to(stringMethodIndex).stop().name } - - navigate(it).to(stringMethodIndex).stop().name } fun extensionInstructions(playbackStartRegister: Int, freeRegister: Int) = @@ -118,33 +88,30 @@ val openShortsInRegularPlayerPatch = bytecodePatch( nop """ - if (!is_19_25_or_greater) { - shortsPlaybackIntentLegacyFingerprint.method.apply { - val index = indexOfFirstInstructionOrThrow { - getReference()?.returnType == - "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;" + if (is_19_25_or_greater) { + shortsPlaybackIntentFingerprint.method.addInstructionsWithLabels( + 0, + """ + move-object/from16 v0, p1 + ${extensionInstructions(0, 1)} + """ + ) + } else { + shortsPlaybackIntentLegacyFingerprint.let { + it.method.apply { + val index = it.instructionMatches.first().index + val playbackStartRegister = getInstruction(index + 1).registerA + val insertIndex = index + 2 + val freeRegister = findFreeRegister(insertIndex, playbackStartRegister) + + addInstructionsWithLabels( + insertIndex, + extensionInstructions(playbackStartRegister, freeRegister) + ) } - val playbackStartRegister = getInstruction(index + 1).registerA - val insertIndex = index + 2 - val freeRegister = findFreeRegister(insertIndex, playbackStartRegister) - - addInstructionsWithLabels( - insertIndex, - extensionInstructions(playbackStartRegister, freeRegister) - ) } - - return@execute } - shortsPlaybackIntentFingerprint.method.addInstructionsWithLabels( - 0, - """ - move-object/from16 v0, p1 - ${extensionInstructions(0, 1)} - """ - ) - // Fix issue with back button exiting the app instead of minimizing the player. // Without this change this issue can be difficult to reproduce, but seems to occur // most often with 'open video in regular player' and not open in fullscreen player. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt index 80eca05575..c8bcb4235c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt @@ -1,58 +1,52 @@ package app.revanced.patches.youtube.layout.sponsorblock +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral +import app.revanced.patches.youtube.shared.seekbarFingerprint +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.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val appendTimeFingerprint = fingerprint { +internal val appendTimeFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Ljava/lang/CharSequence;", "Ljava/lang/CharSequence;", "Ljava/lang/CharSequence;") - opcodes( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, + instructions( + resourceLiteral("string", "total_time"), + + methodCall(smali = "Landroid/content/res/Resources;->getString(I[Ljava/lang/Object;)Ljava/lang/String;"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) ) } -internal val controlsOverlayFingerprint = fingerprint { +internal val controlsOverlayFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) parameters() - opcodes( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, // R.id.inset_overlay_view_layout - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.NEW_INSTANCE, + instructions( + resourceLiteral("id", "inset_overlay_view_layout"), + checkCast("Landroid/widget/FrameLayout;", maxAfter = 20) ) } -internal val rectangleFieldInvalidatorFingerprint = fingerprint { +/** + * Resolves to the class found in [seekbarFingerprint]. + */ +internal val rectangleFieldInvalidatorFingerprint by fingerprint { returns("V") - custom { method, _ -> - val instructions = method.implementation?.instructions!! - val instructionCount = instructions.count() - - // the method has definitely more than 5 instructions - if (instructionCount < 5) return@custom false - - val referenceInstruction = instructions.elementAt(instructionCount - 2) // the second to last instruction - val reference = ((referenceInstruction as? ReferenceInstruction)?.reference as? MethodReference) - - reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method + parameters() + custom { method, _ -> + indexOfInvalidateInstruction(method) >= 0 } } + +internal fun indexOfInvalidateInstruction(method: Method) = + method.indexOfFirstInstructionReversed { + getReference()?.name == "invalidate" + } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt index 04498528ce..28c505caed 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt @@ -3,12 +3,8 @@ package app.revanced.patches.youtube.layout.sponsorblock 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.instructions -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.mapping.resourceMappingPatch @@ -27,11 +23,9 @@ import app.revanced.patches.youtube.video.information.videoTimeHook import app.revanced.patches.youtube.video.videoid.hookBackgroundPlayVideoId import app.revanced.patches.youtube.video.videoid.videoIdPatch import app.revanced.util.* -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.* import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.StringReference private val sponsorBlockResourcePatch = resourcePatch { dependsOn( @@ -80,7 +74,6 @@ private val sponsorBlockResourcePatch = resourcePatch { "revanced_sb_skip_sponsor_button.xml", ), ResourceGroup( - // required resource for back button, because when the base APK is used, this resource will not exist "drawable", "revanced_sb_adjust.xml", "revanced_sb_backward.xml", @@ -99,7 +92,7 @@ private val sponsorBlockResourcePatch = resourcePatch { } } -private const val EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = +internal const val EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/sponsorblock/SegmentPlaybackController;" private const val EXTENSION_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/sponsorblock/ui/CreateSegmentButton;" @@ -115,6 +108,7 @@ val sponsorBlockPatch = bytecodePatch( ) { dependsOn( sharedExtensionPatch, + resourceMappingPatch, videoIdPatch, // Required to skip segments on time. videoInformationPatch, @@ -146,42 +140,58 @@ val sponsorBlockPatch = bytecodePatch( "->setCurrentVideoId(Ljava/lang/String;)V", ) - // Seekbar drawing - seekbarOnDrawFingerprint.match(seekbarFingerprint.originalClassDef).method.apply { - // Get left and right of seekbar rectangle. - val moveRectangleToRegisterIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_OBJECT_FROM16) + // Set seekbar draw rectangle. + val rectangleFieldName : FieldReference + rectangleFieldInvalidatorFingerprint.match(seekbarFingerprint.originalClassDef).method.apply { + val invalidateIndex = indexOfInvalidateInstruction(this) + val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } + rectangleFieldName = getInstruction(rectangleIndex).reference as FieldReference + } - addInstruction( - moveRectangleToRegisterIndex + 1, - "invoke-static/range { p0 .. p0 }, " + - "$EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V", - ) + // Seekbar drawing. - // Set the thickness of the segment. - val thicknessIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_STATIC && getReference()?.name == "round" - } - val thicknessRegister = getInstruction(thicknessIndex).registerC - addInstruction( - thicknessIndex + 2, - "invoke-static { v$thicknessRegister }, " + - "$EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V", - ) + // Shared fingerprint and indexes may have changed. + seekbarOnDrawFingerprint.clearMatch() + // Cannot match using original immutable class because + // class may have been modified by other patches + seekbarOnDrawFingerprint.match(seekbarFingerprint.classDef).let { + it.method.apply { + // Set seekbar thickness. + val thicknessIndex = it.instructionMatches.last().index + val thicknessRegister = getInstruction(thicknessIndex).registerA + addInstruction( + thicknessIndex + 1, + "invoke-static { v$thicknessRegister }, " + + "$EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSeekbarThickness(I)V", + ) - // Find the drawCircle call and draw the segment before it. - val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { - getReference()?.name == "drawCircle" - } - val drawCircleInstruction = getInstruction(drawCircleIndex) - val canvasInstanceRegister = drawCircleInstruction.registerC - val centerYRegister = drawCircleInstruction.registerE + // Find the drawCircle call and draw the segment before it. + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "drawCircle" + } + val drawCircleInstruction = getInstruction(drawCircleIndex) + val canvasInstanceRegister = drawCircleInstruction.registerC + val centerYRegister = drawCircleInstruction.registerE - addInstruction( - drawCircleIndex, - "invoke-static { v$canvasInstanceRegister, v$centerYRegister }, " + - "$EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->" + - "drawSponsorTimeBars(Landroid/graphics/Canvas;F)V", - ) + addInstruction( + drawCircleIndex, + "invoke-static { v$canvasInstanceRegister, v$centerYRegister }, " + + "$EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->" + + "drawSegmentTimeBars(Landroid/graphics/Canvas;F)V", + ) + + // Set seekbar bounds. + addInstructions( + 0, + """ + move-object/from16 v0, p0 + iget-object v0, v0, $rectangleFieldName + invoke-static { v0 }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSeekbarRectangle(Landroid/graphics/Rect;)V + """ + ) + } } // Change visibility of the buttons. @@ -192,17 +202,19 @@ val sponsorBlockPatch = bytecodePatch( injectVisibilityCheckCall(EXTENSION_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR) // Append the new time to the player layout. - val appendTimePatternScanStartIndex = appendTimeFingerprint.patternMatch!!.startIndex - appendTimeFingerprint.method.apply { - val register = getInstruction(appendTimePatternScanStartIndex + 1).registerA - - addInstructions( - appendTimePatternScanStartIndex + 2, - """ - invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$register - """, - ) + appendTimeFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA + + addInstructions( + index + 1, + """ + invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$register + """ + ) + } } // Initialize the player controller. @@ -210,48 +222,16 @@ val sponsorBlockPatch = bytecodePatch( // Initialize the SponsorBlock view. controlsOverlayFingerprint.match(layoutConstructorFingerprint.originalClassDef).let { - val startIndex = it.patternMatch!!.startIndex + val checkCastIndex = it.instructionMatches.last().index it.method.apply { - val frameLayoutRegister = (getInstruction(startIndex + 2) as OneRegisterInstruction).registerA + val frameLayoutRegister = getInstruction(checkCastIndex).registerA addInstruction( - startIndex + 3, + checkCastIndex + 1, "invoke-static {v$frameLayoutRegister}, $EXTENSION_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V", ) } } - // Set seekbar draw rectangle. - rectangleFieldInvalidatorFingerprint.match(seekbarOnDrawFingerprint.originalClassDef).method.apply { - val fieldIndex = instructions.count() - 3 - val fieldReference = getInstruction(fieldIndex).reference as FieldReference - - // replace the "replaceMeWith*" strings - proxy(classes.first { it.type.endsWith("SegmentPlaybackController;") }) - .mutableClass - .methods - .find { it.name == "setSponsorBarRect" } - ?.let { method -> - fun MutableMethod.replaceStringInstruction(index: Int, instruction: Instruction, with: String) { - val register = (instruction as OneRegisterInstruction).registerA - this.replaceInstruction( - index, - "const-string v$register, \"$with\"", - ) - } - for ((index, it) in method.instructions.withIndex()) { - if (it.opcode.ordinal != Opcode.CONST_STRING.ordinal) continue - - when (((it as ReferenceInstruction).reference as StringReference).string) { - "replaceMeWithsetSponsorBarRect" -> method.replaceStringInstruction( - index, - it, - fieldReference.name, - ) - } - } - } ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings") - } - // The vote and create segment buttons automatically change their visibility when appropriate, // but if buttons are showing when the end of the video is reached then they will not automatically hide. // Add a hook to forcefully hide when the end of the video is reached. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt index ac458cec26..855486174a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt @@ -1,31 +1,28 @@ package app.revanced.patches.youtube.layout.spoofappversion +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral 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 toolBarButtonFingerprint = fingerprint { +internal val toolBarButtonFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Landroid/view/MenuItem;") - custom { method, _ -> - method.containsLiteralInstruction(menuItemView) && - indexOfGetDrawableInstruction(method) >= 0 - } -} - -internal fun indexOfGetDrawableInstruction(method: Method) = method.indexOfFirstInstruction { - val reference = getReference() - reference?.definingClass == "Landroid/content/res/Resources;" && - reference.name == "getDrawable" + instructions( + resourceLiteral("id", "menu_item_view"), + methodCall(returnType = "I", opcode = Opcode.INVOKE_INTERFACE), + opcode(Opcode.MOVE_RESULT, maxAfter = 0), // Value is zero if resource does not exist. + fieldAccess(type = "Landroid/widget/ImageView;", opcode = Opcode.IGET_OBJECT, maxAfter = 6), + methodCall("Landroid/content/res/Resources;", "getDrawable", maxAfter = 8), + methodCall("Landroid/widget/ImageView;", "setImageDrawable", maxAfter = 4) + ) } -internal val spoofAppVersionFingerprint = fingerprint { +internal val spoofAppVersionFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("L") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt index 469d478df8..81f2d87f6d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt @@ -4,13 +4,10 @@ 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.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting @@ -20,25 +17,7 @@ import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal var menuItemView = -1L - private set - -internal val spoofAppVersionResourcePatch = resourcePatch { - dependsOn( - resourceMappingPatch - ) - - execute { - menuItemView = resourceMappings["id", "menu_item_view"] - } -} private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/spoof/SpoofAppVersionPatch;" @@ -49,7 +28,7 @@ val spoofAppVersionPatch = bytecodePatch( "This can be used to restore old UI elements and features." ) { dependsOn( - spoofAppVersionResourcePatch, + resourceMappingPatch, sharedExtensionPatch, settingsPatch, addResourcesPatch, @@ -79,14 +58,10 @@ val spoofAppVersionPatch = bytecodePatch( preferences = setOf( SwitchPreference("revanced_spoof_app_version"), if (is_19_43_or_greater) { - ListPreference( - key = "revanced_spoof_app_version_target", - summaryKey = null - ) + ListPreference("revanced_spoof_app_version_target") } else { ListPreference( key = "revanced_spoof_app_version_target", - summaryKey = null, entriesKey = "revanced_spoof_app_version_target_legacy_entries", entryValuesKey = "revanced_spoof_app_version_target_legacy_entry_values" ) @@ -100,35 +75,27 @@ val spoofAppVersionPatch = bytecodePatch( * missing image resources. As a workaround, do not set an image in the * toolbar when the enum name is UNKNOWN. */ - toolBarButtonFingerprint.method.apply { - val getDrawableIndex = indexOfGetDrawableInstruction(this) - val enumOrdinalIndex = indexOfFirstInstructionReversedOrThrow(getDrawableIndex) { - opcode == Opcode.INVOKE_INTERFACE && - getReference()?.returnType == "I" - } - val insertIndex = enumOrdinalIndex + 2 - val insertRegister = getInstruction(insertIndex - 1).registerA - val jumpIndex = indexOfFirstInstructionOrThrow(insertIndex) { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "setImageDrawable" - } + 1 + toolBarButtonFingerprint.apply { + val imageResourceIndex = instructionMatches[2].index + val register = method.getInstruction(imageResourceIndex).registerA + val jumpIndex = instructionMatches.last().index + 1 - addInstructionsWithLabels( - insertIndex, - "if-eqz v$insertRegister, :ignore", - ExternalLabel("ignore", getInstruction(jumpIndex)) + method.addInstructionsWithLabels( + imageResourceIndex + 1, + "if-eqz v$register, :ignore", + ExternalLabel("ignore", method.getInstruction(jumpIndex)) ) } spoofAppVersionFingerprint.apply { - val startIndex = patternMatch!!.startIndex - val buildOverrideNameRegister = method.getInstruction(startIndex).registerA + val index = instructionMatches.first().index + val register = method.getInstruction(index).registerA method.addInstructions( - startIndex + 1, + index + 1, """ - invoke-static {v$buildOverrideNameRegister}, $EXTENSION_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$buildOverrideNameRegister + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$register """ ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt index 0220840203..bf6722d1fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt @@ -1,14 +1,17 @@ package app.revanced.patches.youtube.layout.startpage import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.Opcode -internal val intentActionFingerprint = fingerprint { +internal val intentActionFingerprint by fingerprint { parameters("Landroid/content/Intent;") - strings("has_handled_intent") + instructions( + string("has_handled_intent") + ) } -internal val browseIdFingerprint = fingerprint { +internal val browseIdFingerprint by fingerprint { returns("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;") parameters() opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt index 12c59a3beb..86f4048def 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt @@ -1,20 +1,19 @@ package app.revanced.patches.youtube.layout.startupshortsreset import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_03_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.findFreeRegister import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference @@ -30,6 +29,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, + versionCheckPatch ) compatibleWith( @@ -49,45 +49,41 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( SwitchPreference("revanced_disable_resuming_shorts_player"), ) - if (is_20_02_or_greater) { + if (is_20_03_or_greater) { userWasInShortsAlternativeFingerprint.let { it.method.apply { - val stringIndex = it.stringMatches!!.first().index - val booleanValueIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "booleanValue" - } - val booleanValueRegister = - getInstruction(booleanValueIndex + 1).registerA + val match = it.instructionMatches[2] + val insertIndex = match.index + 1 + val register = match.getInstruction().registerA addInstructions( - booleanValueIndex + 2, """ - invoke-static {v$booleanValueRegister}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z - move-result v$booleanValueRegister - """ + insertIndex, + """ + invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z + move-result v$register + """ ) } } } else { userWasInShortsLegacyFingerprint.method.apply { val listenableInstructionIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() opcode == Opcode.INVOKE_INTERFACE && - reference?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && - reference.name == "isDone" + getReference()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && + getReference()?.name == "isDone" } val freeRegister = findFreeRegister(listenableInstructionIndex) addInstructionsAtControlFlowLabel( listenableInstructionIndex, """ - invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z + invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z move-result v$freeRegister - if-eqz v$freeRegister, :show + if-eqz v$freeRegister, :show_startup_shorts_player return-void - :show + :show_startup_shorts_player nop - """ + """, ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt index b1fab6fcb9..d668510541 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt @@ -1,33 +1,49 @@ package app.revanced.patches.youtube.layout.startupshortsreset +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode /** - * YouTube 20.02.08 ~ + * 20.02+ */ -internal val userWasInShortsAlternativeFingerprint = fingerprint { +internal val userWasInShortsAlternativeFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Ljava/lang/Object;") - strings("userIsInShorts: ") + instructions( + checkCast("Ljava/lang/Boolean;"), + methodCall(smali = "Ljava/lang/Boolean;->booleanValue()Z", maxAfter = 0), + opcode(Opcode.MOVE_RESULT, maxAfter = 0), + string("userIsInShorts: ", maxAfter = 5) + ) } -internal val userWasInShortsLegacyFingerprint = fingerprint { +/** + * Pre 20.02 + */ +internal val userWasInShortsLegacyFingerprint by fingerprint { returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("Ljava/lang/Object;") - strings("Failed to read user_was_in_shorts proto after successful warmup") + instructions( + string("Failed to read user_was_in_shorts proto after successful warmup") + ) } /** * 18.15.40+ */ -internal val userWasInShortsConfigFingerprint = fingerprint { +internal val userWasInShortsConfigFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") - literal { - 45358360L - } + parameters() + instructions( + literal(45358360L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt deleted file mode 100644 index c04f5e99c7..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatch.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.tablet - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.youtube.layout.formfactor.changeFormFactorPatch - -@Deprecated("Use 'Change form factor' instead.") -val enableTabletLayoutPatch = bytecodePatch { - dependsOn(changeFormFactorPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt index 8864c20c6f..3ddca89fa9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt @@ -1,41 +1,58 @@ package app.revanced.patches.youtube.layout.theme +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val lithoThemeFingerprint = fingerprint { +internal val lithoThemeFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returns("V") parameters("Landroid/graphics/Rect;") - opcodes( - Opcode.IGET, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID, + instructions( + fieldAccess( + opcode = Opcode.IPUT_OBJECT, + definingClass = "this", + type = "Landroid/graphics/Path;" + ), + + methodCall( + definingClass = "this", + name = "isStateful", + returnType = "Z", + maxAfter = 5 + ), + + fieldAccess( + opcode = Opcode.IGET_OBJECT, + definingClass = "this", + type = "Landroid/graphics/Paint", + maxAfter = 5 + ), + methodCall( + smali = "Landroid/graphics/Paint;->setColor(I)V", + maxAfter = 0 + ) ) custom { method, _ -> method.name == "onBoundsChange" } } -internal const val GRADIENT_LOADING_SCREEN_AB_CONSTANT = 45412406L - -internal val useGradientLoadingScreenFingerprint = fingerprint { - literal { GRADIENT_LOADING_SCREEN_AB_CONSTANT } +internal val useGradientLoadingScreenFingerprint by fingerprint { + instructions( + literal(45412406L) + ) } -internal const val SPLASH_SCREEN_STYLE_FEATURE_FLAG = 269032877L - -internal val splashScreenStyleFingerprint = fingerprint { +internal val splashScreenStyleFingerprint by fingerprint { returns("V") parameters("Landroid/os/Bundle;") - literal { SPLASH_SCREEN_STYLE_FEATURE_FLAG } + instructions( + literal(269032877L) + ) custom { method, classDef -> method.name == "onCreate" && classDef.endsWith("/MainActivity;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt index fdab6c4b8b..6ca91d1e95 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/LithoColorHookPatch.kt @@ -3,6 +3,9 @@ package app.revanced.patches.youtube.layout.theme import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch +/** + * Hooks most color usage of litho components. + */ lateinit var lithoColorOverrideHook: (targetMethodClass: String, targetMethodName: String) -> Unit private set @@ -11,8 +14,7 @@ val lithoColorHookPatch = bytecodePatch( ) { execute { - - var insertionIndex = lithoThemeFingerprint.patternMatch!!.endIndex - 1 + var insertionIndex = lithoThemeFingerprint.instructionMatches.last().index lithoColorOverrideHook = { targetMethodClass, targetMethodName -> lithoThemeFingerprint.method.addInstructions( @@ -20,7 +22,7 @@ val lithoColorHookPatch = bytecodePatch( """ invoke-static { p1 }, $targetMethodClass->$targetMethodName(I)I move-result p1 - """, + """ ) insertionIndex += 2 } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt index 608be70bac..e80a369233 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt @@ -225,17 +225,21 @@ val themePatch = bytecodePatch( ) } - useGradientLoadingScreenFingerprint.method.insertLiteralOverride( - GRADIENT_LOADING_SCREEN_AB_CONSTANT, - "$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z" - ) + useGradientLoadingScreenFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z" + ) + } if (is_19_47_or_greater) { // Lottie splash screen exists in earlier versions, but it may not be always on. - splashScreenStyleFingerprint.method.insertLiteralOverride( - SPLASH_SCREEN_STYLE_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I" - ) + splashScreenStyleFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + "$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I" + ) + } } lithoColorOverrideHook(EXTENSION_CLASS_DESCRIPTOR, "getValue") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt index a2e888b83e..8077b45c68 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -6,9 +6,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch @@ -29,7 +28,7 @@ private val backgroundPlaybackResourcePatch = resourcePatch { dependsOn(resourceMappingPatch, addResourcesPatch) execute { - prefBackgroundAndOfflineCategoryId = resourceMappings["string", "pref_background_and_offline_category"] + prefBackgroundAndOfflineCategoryId = getResourceId("string", "pref_background_and_offline_category") } } @@ -105,10 +104,12 @@ val backgroundPlaybackPatch = bytecodePatch( // Fix PiP buttons not working after locking/unlocking device screen. if (is_19_34_or_greater) { - pipInputConsumerFeatureFlagFingerprint.method.insertLiteralOverride( - PIP_INPUT_CONSUMER_FEATURE_FLAG, - false - ) + pipInputConsumerFeatureFlagFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + false + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt index a5c077115d..23a6903bc4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val backgroundPlaybackManagerFingerprint = fingerprint { +internal val backgroundPlaybackManagerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("L") @@ -38,7 +38,7 @@ internal val backgroundPlaybackManagerFingerprint = fingerprint { ) } -internal val backgroundPlaybackSettingsFingerprint = fingerprint { +internal val backgroundPlaybackSettingsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters() @@ -54,7 +54,7 @@ internal val backgroundPlaybackSettingsFingerprint = fingerprint { literal { prefBackgroundAndOfflineCategoryId } } -internal val kidsBackgroundPlaybackPolicyControllerFingerprint = fingerprint { +internal val kidsBackgroundPlaybackPolicyControllerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("I", "L", "L") @@ -71,23 +71,28 @@ internal val kidsBackgroundPlaybackPolicyControllerFingerprint = fingerprint { literal { 5 } } -internal val backgroundPlaybackManagerShortsFingerprint = fingerprint { +internal val backgroundPlaybackManagerShortsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("L") - literal { 151635310 } + instructions( + app.revanced.patcher.literal(151635310) + ) } -internal val shortsBackgroundPlaybackFeatureFlagFingerprint = fingerprint { +internal val shortsBackgroundPlaybackFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { 45415425 } + instructions( + app.revanced.patcher.literal(45415425) + ) } -internal const val PIP_INPUT_CONSUMER_FEATURE_FLAG = 45638483L - // Fix 'E/InputDispatcher: Window handle pip_input_consumer has no registered input channel' -internal val pipInputConsumerFeatureFlagFingerprint = fingerprint { - literal { PIP_INPUT_CONSUMER_FEATURE_FLAG} +internal val pipInputConsumerFeatureFlagFingerprint by fingerprint { + instructions( + // PiP input consumer feature flag. + app.revanced.patcher.literal(45638483L) + ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/Fingerprints.kt index 33e188974b..03ba7a99be 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/Fingerprints.kt @@ -1,34 +1,37 @@ package app.revanced.patches.youtube.misc.debugging import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -internal val experimentalFeatureFlagParentFingerprint = fingerprint { +internal val experimentalFeatureFlagParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("L") parameters("L", "J", "[B") - strings("Unable to parse proto typed experiment flag: ") + instructions( + string("Unable to parse proto typed experiment flag: ") + ) } -internal val experimentalBooleanFeatureFlagFingerprint = fingerprint { +internal val experimentalBooleanFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("Z") parameters("L", "J", "Z") } -internal val experimentalDoubleFeatureFlagFingerprint = fingerprint { +internal val experimentalDoubleFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("D") parameters("J", "D") } -internal val experimentalLongFeatureFlagFingerprint = fingerprint { +internal val experimentalLongFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("J") parameters("J", "J") } -internal val experimentalStringFeatureFlagFingerprint = fingerprint { +internal val experimentalStringFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters("J", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/Fingerprints.kt index 4f99a4cf54..6d772c5169 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/Fingerprints.kt @@ -1,8 +1,12 @@ package app.revanced.patches.youtube.misc.dimensions.spoof import app.revanced.patcher.fingerprint +import app.revanced.patcher.string -internal val deviceDimensionsModelToStringFingerprint = fingerprint { +internal val deviceDimensionsModelToStringFingerprint by fingerprint { returns("L") - strings("minh.", ";maxh.") + instructions( + string("minh."), + string(";maxh.") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt index 9ce0001ac3..11bc3a7a8e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt @@ -44,7 +44,7 @@ val spoofDeviceDimensionsPatch = bytecodePatch( // Override the parameters containing the dimensions. .addInstructions( 1, // Add after super call. - mapOf( + arrayOf( 1 to "MinHeightOrWidth", // p1 = min height 2 to "MaxHeightOrWidth", // p2 = max height 3 to "MinHeightOrWidth", // p3 = min width diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/extension/hooks/ApplicationInitHook.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/extension/hooks/ApplicationInitHook.kt index 6a0e7d1f48..8f2274d83d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/extension/hooks/ApplicationInitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/extension/hooks/ApplicationInitHook.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.misc.extension.hooks +import app.revanced.patcher.string import app.revanced.patches.shared.misc.extension.extensionHook /** @@ -7,5 +8,8 @@ import app.revanced.patches.shared.misc.extension.extensionHook */ // Extension context is the Activity itself. internal val applicationInitHook = extensionHook { - strings("Application creation", "Application.onCreate") + instructions( + string("Application.onCreate"), + string("Application creation") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt index 3de2e836ad..3fb5562a8b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt @@ -1,10 +1,14 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.AccessFlags +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal val scrollPositionFingerprint = fingerprint { +internal val scrollPositionFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returns("V") parameters("L") @@ -16,44 +20,16 @@ internal val scrollPositionFingerprint = fingerprint { strings("scroll_position") } -/** - * Resolves using class found in [recyclerViewTopScrollingParentFingerprint]. - */ -internal val recyclerViewTopScrollingFingerprint = fingerprint { +internal val recyclerViewTopScrollingFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() - opcodes( - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - ) -} - -internal val recyclerViewTopScrollingParentFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - parameters("L", "L", "Landroid/view/ViewGroup;", "Landroid/view/ViewGroup;") - opcodes( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.NEW_INSTANCE, + instructions( + methodCall(smali = "Ljava/util/Iterator;->next()Ljava/lang/Object;"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), + checkCast("Landroid/support/v7/widget/RecyclerView;", maxAfter = 0), + literal(0, maxAfter = 0), + methodCall(definingClass = "Landroid/support/v7/widget/RecyclerView;", maxAfter = 0), + opcode(Opcode.GOTO, maxAfter = 0) ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt index d64857769f..f299aab385 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt @@ -3,6 +3,7 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.youtube.shared.mainActivityOnBackPressedFingerprint +import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -15,17 +16,16 @@ internal val fixBackToExitGesturePatch = bytecodePatch( ) { execute { - recyclerViewTopScrollingFingerprint.match(recyclerViewTopScrollingParentFingerprint.originalClassDef) - .let { - it.method.addInstruction( - it.patternMatch!!.endIndex, - "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onTopView()V" - ) - } + recyclerViewTopScrollingFingerprint.let { + it.method.addInstructionsAtControlFlowLabel( + it.instructionMatches.last().index + 1, + "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onTopView()V" + ) + } scrollPositionFingerprint.let { navigate(it.originalMethod) - .to(it.patternMatch!!.startIndex + 1) + .to(it.instructionMatches.first().index + 1) .stop().apply { val index = indexOfFirstInstructionOrThrow { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch.kt deleted file mode 100644 index 89e7cc08f8..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.fix.playback - -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("Use app.revanced.patches.youtube.misc.spoof.spoofVideoStreamsPatch instead.") -@Suppress("unused") -val spoofVideoStreamsPatch = bytecodePatch { - dependsOn(app.revanced.patches.youtube.misc.spoof.spoofVideoStreamsPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch.kt deleted file mode 100644 index eb4c9492be..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.fix.playback - -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("Use app.revanced.patches.youtube.misc.spoof.userAgentClientSpoofPatch instead.") -@Suppress("unused") -val userAgentClientSpoofPatch = bytecodePatch { - dependsOn(app.revanced.patches.youtube.misc.spoof.userAgentClientSpoofPatch) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playbackspeed/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playbackspeed/Fingerprints.kt index d5a255ca5f..9ae70b23be 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playbackspeed/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playbackspeed/Fingerprints.kt @@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference * This method is usually used to set the initial speed (1.0x) when playback starts from the feed. * For some reason, in the latest YouTube, it is invoked even after the video has already started. */ -internal val playbackSpeedInFeedsFingerprint = fingerprint { +internal val playbackSpeedInFeedsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt index 673fa240a8..93e912addc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt @@ -3,44 +3,17 @@ package app.revanced.patches.youtube.misc.gms import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/AccountCredentialsInvalidTextPatch;" -internal var ic_offline_no_content_upside_down = -1L - private set -internal var offline_no_content_body_text_not_offline_eligible = -1L - private set - -private val accountCredentialsInvalidTextResourcePatch = resourcePatch { - execute { - ic_offline_no_content_upside_down = resourceMappings[ - "drawable", - "ic_offline_no_content_upside_down" - ] - - offline_no_content_body_text_not_offline_eligible = resourceMappings[ - "string", - "offline_no_content_body_text_not_offline_eligible" - ] - } -} - internal val accountCredentialsInvalidTextPatch = bytecodePatch { dependsOn( sharedExtensionPatch, - accountCredentialsInvalidTextResourcePatch, addResourcesPatch ) @@ -60,18 +33,12 @@ internal val accountCredentialsInvalidTextPatch = bytecodePatch { specificNetworkErrorViewControllerFingerprint, loadingFrameLayoutControllerFingerprint ).forEach { fingerprint -> - fingerprint.method.apply { - val resourceIndex = indexOfFirstLiteralInstructionOrThrow( - offline_no_content_body_text_not_offline_eligible - ) - val getStringIndex = indexOfFirstInstructionOrThrow(resourceIndex) { - val reference = getReference() - reference?.name == "getString" - } - val register = getInstruction(getStringIndex + 1).registerA + fingerprint.apply { + val index = instructionMatches.last().index + val register = method.getInstruction(index).registerA - addInstructions( - getStringIndex + 2, + method.addInstructions( + index + 1, """ invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getOfflineNetworkErrorString(Ljava/lang/String;)Ljava/lang/String; move-result-object v$register diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt index 3f4a521df6..315901ba41 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt @@ -1,27 +1,34 @@ package app.revanced.patches.youtube.misc.gms import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal val specificNetworkErrorViewControllerFingerprint = fingerprint { +internal val specificNetworkErrorViewControllerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() - custom { method, _ -> - method.containsLiteralInstruction(ic_offline_no_content_upside_down) - && method.containsLiteralInstruction(offline_no_content_body_text_not_offline_eligible) - } + instructions( + resourceLiteral("drawable", "ic_offline_no_content_upside_down"), + resourceLiteral("string", "offline_no_content_body_text_not_offline_eligible"), + methodCall(name = "getString", returnType = "Ljava/lang/String;"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) + ) } // It's not clear if this second class is ever used and it may be dead code, // but it the layout image/text is identical to the network error fingerprint above. -internal val loadingFrameLayoutControllerFingerprint = fingerprint { +internal val loadingFrameLayoutControllerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") - custom { method, _ -> - method.containsLiteralInstruction(ic_offline_no_content_upside_down) - && method.containsLiteralInstruction(offline_no_content_body_text_not_offline_eligible) - } + instructions( + resourceLiteral("drawable", "ic_offline_no_content_upside_down"), + resourceLiteral("string", "offline_no_content_body_text_not_offline_eligible"), + methodCall(name = "getString", returnType = "Ljava/lang/String;"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) + ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt index 13efc46931..d556efa94d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt @@ -2,22 +2,22 @@ package app.revanced.patches.youtube.misc.hapticfeedback import app.revanced.patcher.fingerprint -internal val markerHapticsFingerprint = fingerprint { +internal val markerHapticsFingerprint by fingerprint { returns("V") strings("Failed to execute markers haptics vibrate.") } -internal val scrubbingHapticsFingerprint = fingerprint { +internal val scrubbingHapticsFingerprint by fingerprint { returns("V") strings("Failed to haptics vibrate for fine scrubbing.") } -internal val seekUndoHapticsFingerprint = fingerprint { +internal val seekUndoHapticsFingerprint by fingerprint { returns("V") strings("Failed to execute seek undo haptics vibrate.") } -internal val zoomHapticsFingerprint = fingerprint { +internal val zoomHapticsFingerprint by fingerprint { returns("V") strings("Failed to haptics vibrate for video zoom") } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt index fcd5298acf..52315bc699 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.youtube.misc.imageurlhook import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -internal val onFailureFingerprint = fingerprint { +internal val onFailureFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters( @@ -17,7 +18,7 @@ internal val onFailureFingerprint = fingerprint { } // Acts as a parent fingerprint. -internal val onResponseStartedFingerprint = fingerprint { +internal val onResponseStartedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;") @@ -32,7 +33,7 @@ internal val onResponseStartedFingerprint = fingerprint { } } -internal val onSucceededFingerprint = fingerprint { +internal val onSucceededFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;") @@ -43,22 +44,23 @@ internal val onSucceededFingerprint = fingerprint { internal const val CRONET_URL_REQUEST_CLASS_DESCRIPTOR = "Lorg/chromium/net/impl/CronetUrlRequest;" -internal val requestFingerprint = fingerprint { +internal val requestFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") custom { _, classDef -> classDef.type == CRONET_URL_REQUEST_CLASS_DESCRIPTOR } } -internal val messageDigestImageUrlFingerprint = fingerprint { +internal val messageDigestImageUrlFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters("Ljava/lang/String;", "L") } -internal val messageDigestImageUrlParentFingerprint = fingerprint { +internal val messageDigestImageUrlParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/String;") parameters() - strings("@#&=*+-_.,:!?()/~'%;\$") + instructions( + string("@#&=*+-_.,:!?()/~'%;\$"), + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt index 3968af3f03..499f9d3e5f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt @@ -7,17 +7,11 @@ import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.misc.playservice.is_19_33_or_greater -import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -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.instruction.FiveRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.TypeReference + +private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/BypassURLRedirectsPatch;" val bypassURLRedirectsPatch = bytecodePatch( name = "Bypass URL redirects", @@ -27,7 +21,6 @@ val bypassURLRedirectsPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, - versionCheckPatch, ) compatibleWith( @@ -47,41 +40,20 @@ val bypassURLRedirectsPatch = bytecodePatch( SwitchPreference("revanced_bypass_url_redirects"), ) - val fingerprints = if (is_19_33_or_greater) { - arrayOf( - abUriParserFingerprint, - httpUriParserFingerprint, - ) - } else { - arrayOf( - abUriParserLegacyFingerprint, - httpUriParserLegacyFingerprint, - ) - } - - fingerprints.forEach { - it.method.apply { - val insertIndex = findUriParseIndex() + arrayOf( + abUriParserFingerprint, + httpUriParserFingerprint, + ).forEach { fingerprint -> + fingerprint.method.apply { + val insertIndex = fingerprint.instructionMatches.first().index val uriStringRegister = getInstruction(insertIndex).registerC replaceInstruction( insertIndex, - "invoke-static {v$uriStringRegister}," + - "Lapp/revanced/extension/youtube/patches/BypassURLRedirectsPatch;" + - "->" + - "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;", + "invoke-static { v$uriStringRegister }, ${EXTENSION_CLASS_DESCRIPTOR}->" + + "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;", ) } } } } - -internal fun Method.findUriParseIndex() = indexOfFirstInstruction { - val reference = getReference() - reference?.returnType == "Landroid/net/Uri;" && reference.name == "parse" -} - -internal fun Method.findWebViewCheckCastIndex() = indexOfFirstInstruction { - val reference = getReference() - opcode == Opcode.CHECK_CAST && reference?.type?.endsWith("/WebviewEndpointOuterClass${'$'}WebviewEndpoint;") == true -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt index 6f231693bd..7ad6cab6d7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt @@ -1,68 +1,35 @@ package app.revanced.patches.youtube.misc.links +import app.revanced.patcher.checkCast +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -/** - * Target 19.33+ - */ -internal val abUriParserFingerprint = fingerprint { +internal val abUriParserFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Ljava/lang/Object") - parameters("Ljava/lang/Object") - custom { method, _ -> - method.findUriParseIndex() >= 0 && method.findWebViewCheckCastIndex() >= 0 - } -} - -/** - * Target 19.33+ - */ -internal val httpUriParserFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Landroid/net/Uri") - parameters("Ljava/lang/String") - strings("https", "://", "https:") - custom { methodDef, _ -> - methodDef.findUriParseIndex() >= 0 - } -} - -internal val abUriParserLegacyFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Ljava/lang/Object") - parameters("Ljava/lang/Object") - opcodes( - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, + returns("Ljava/lang/Object;") + parameters("Ljava/lang/Object;") + instructions( + methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"), + fieldAccess( + definingClass = "/WebviewEndpointOuterClass${'$'}WebviewEndpoint;", + name = "webviewEndpoint" + ), + checkCast("/WebviewEndpointOuterClass${'$'}WebviewEndpoint;"), ) - custom { methodDef, classDef -> - // This method is always called "a" because this kind of class always has a single (non-synthetic) method. - - if (methodDef.name != "a") return@custom false - - val count = classDef.methods.count() - count == 2 || count == 3 - } } -internal val httpUriParserLegacyFingerprint = fingerprint { +internal val httpUriParserFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Landroid/net/Uri") - parameters("Ljava/lang/String") - opcodes( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, + returns("Landroid/net/Uri;") + parameters("Ljava/lang/String;") + instructions( + methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"), + string("https"), + string("://"), + string("https:"), ) - strings("://") } + diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt index 8ef0161d19..0740c3b694 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt @@ -1,38 +1,52 @@ package app.revanced.patches.youtube.misc.litho.filter +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint import app.revanced.util.containsLiteralInstruction -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val componentContextParserFingerprint = fingerprint { - strings( - "TreeNode result must be set.", - // String is a partial match and changed slightly in 20.03+ - "it was removed due to duplicate converter bindings." +internal val componentContextParserFingerprint by fingerprint { + instructions( + string("Number of bits must be positive") ) } -/** - * Resolves to the class found in [componentContextParserFingerprint]. - * When patching 19.16 this fingerprint matches the same method as [componentContextParserFingerprint]. - */ -internal val componentContextSubParserFingerprint = fingerprint { - strings( - "Number of bits must be positive" +internal val componentCreateFingerprint by fingerprint { + instructions( + string("Element missing correct type extension"), + string("Element missing type") ) } -internal val lithoFilterFingerprint = fingerprint { +internal val lithoFilterFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - returns("V") custom { _, classDef -> classDef.endsWith("/LithoFilterPatch;") } } -internal val protobufBufferReferenceFingerprint = fingerprint { +internal val protobufBufferReferenceFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("V") + parameters("[B") + instructions( + fieldAccess( + opcode = Opcode.IGET_OBJECT, + definingClass = "this", + type = "Lcom/google/android/libraries/elements/adl/UpbMessage;" + ), + methodCall( + definingClass = "Lcom/google/android/libraries/elements/adl/UpbMessage;", + name = "jniDecode" + ) + ) +} + +internal val protobufBufferReferenceLegacyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("I", "Ljava/nio/ByteBuffer;") @@ -44,16 +58,18 @@ internal val protobufBufferReferenceFingerprint = fingerprint { ) } -internal val emptyComponentFingerprint = fingerprint { +internal val emptyComponentFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.CONSTRUCTOR) parameters() - strings("EmptyComponent") + instructions( + string("EmptyComponent") + ) custom { _, classDef -> classDef.methods.filter { AccessFlags.STATIC.isSet(it.accessFlags) }.size == 1 } } -internal val lithoThreadExecutorFingerprint = fingerprint { +internal val lithoThreadExecutorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters("I", "I", "I") custom { method, classDef -> @@ -62,16 +78,18 @@ internal val lithoThreadExecutorFingerprint = fingerprint { } } -internal val lithoComponentNameUpbFeatureFlagFingerprint = fingerprint { +internal val lithoComponentNameUpbFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { 45631264L } + instructions( + literal(45631264L) + ) } -internal val lithoConverterBufferUpbFeatureFlagFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) +internal val lithoConverterBufferUpbFeatureFlagFingerprint by fingerprint { returns("L") - parameters("L") - literal { 45419603L } + instructions( + literal(45419603L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index bc17028f2b..605d3b5c66 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -9,22 +9,24 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater import app.revanced.patches.youtube.misc.playservice.is_20_05_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_22_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.shared.conversionContextFingerprintToString import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.findFreeRegister -import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.insertLiteralOverride +import app.revanced.util.returnLate import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -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.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import java.util.logging.Logger lateinit var addLithoFilter: (String) -> Unit private set @@ -70,12 +72,6 @@ val lithoFilterPatch = bytecodePatch( * public Component parseComponent() { * ... * - * // Checks if the component should be filtered. - * // Sets a thread local with the filtering result. - * extensionClass.filter(identifier, pathBuilder); // Inserted by this patch. - * - * ... - * * if (extensionClass.shouldFilter()) { // Inserted by this patch. * return emptyComponent; * } @@ -97,114 +93,96 @@ val lithoFilterPatch = bytecodePatch( invoke-direct { v1 }, $classDescriptor->()V const/16 v2, ${filterCount++} aput-object v1, v0, v2 - """, + """ ) } } // region Pass the buffer into extension. - protobufBufferReferenceFingerprint.method.addInstruction( + if (is_19_25_or_greater) { + // Hook method that bridges between UPB buffer native code and FB Litho. + protobufBufferReferenceFingerprint.let { + // Hook the buffer after the call to jniDecode(). + it.method.addInstruction( + it.instructionMatches.last().index + 1, + "invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->setProtoBuffer([B)V", + ) + } + } + + // Legacy Non native buffer. + protobufBufferReferenceLegacyFingerprint.method.addInstruction( 0, "invoke-static { p2 }, $EXTENSION_CLASS_DESCRIPTOR->setProtoBuffer(Ljava/nio/ByteBuffer;)V", ) // endregion - // region Hook the method that parses bytes into a ComponentContext. - // Allow the method to run to completion, and override the - // return value with an empty component if it should be filtered. - // It is important to allow the original code to always run to completion, - // otherwise memory leaks and poor app performance can occur. - // - // The extension filtering result needs to be saved off somewhere, but cannot - // save to a class field since the target class is called by multiple threads. - // It would be great if there was a way to change the register count of the - // method implementation and save the result to a high register to later use - // in the method, but there is no simple way to do that. - // Instead save the extension filter result to a thread local and check the - // filtering result at each method return index. - // String field for the litho identifier. - componentContextParserFingerprint.method.apply { - val conversionContextClass = conversionContextFingerprintToString.originalClassDef - - val conversionContextIdentifierField = componentContextSubParserFingerprint.match( - componentContextParserFingerprint.originalClassDef - ).let { - // Identifier field is loaded just before the string declaration. - val index = it.method.indexOfFirstInstructionReversedOrThrow( - it.stringMatches!!.first().index - ) { - val reference = getReference() - reference?.definingClass == conversionContextClass.type - && reference.type == "Ljava/lang/String;" - } - it.method.getInstruction(index).getReference() + // region Modify the create component method and + // if the component is filtered then return an empty component. + + // Find the identifier/path fields of the conversion context. + val conversionContextIdentifierField = componentContextParserFingerprint.match().let { + // Identifier field is loaded just before the string declaration. + val index = it.method.indexOfFirstInstructionReversedOrThrow( + it.instructionMatches.first().index + ) { + val reference = getReference() + reference?.definingClass == conversionContextFingerprintToString.originalClassDef.type + && reference.type == "Ljava/lang/String;" } - // StringBuilder field for the litho path. - val conversionContextPathBuilderField = conversionContextClass.fields - .single { field -> field.type == "Ljava/lang/StringBuilder;" } + it.method.getInstruction(index).getReference()!! + } - val conversionContextResultIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.returnType == conversionContextClass.type - } + 1 + val conversionContextPathBuilderField = conversionContextFingerprintToString.originalClassDef + .fields.single { field -> field.type == "Ljava/lang/StringBuilder;" } - val conversionContextResultRegister = getInstruction( - conversionContextResultIndex - ).registerA + // Find class and methods to create an empty component. + val builderMethodDescriptor = emptyComponentFingerprint.classDef.methods.single { + // The only static method in the class. + method -> AccessFlags.STATIC.isSet(method.accessFlags) + } + val emptyComponentField = classBy { + // Only one field that matches. + it.type == builderMethodDescriptor.returnType + }.fields.single() + + componentCreateFingerprint.method.apply { + val insertIndex = if (is_19_17_or_greater) { + indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT) + } else { + // 19.16 clobbers p2 so must check at start of the method and not at the return index. + 0 + } - val identifierRegister = findFreeRegister( - conversionContextResultIndex, conversionContextResultRegister - ) - val stringBuilderRegister = findFreeRegister( - conversionContextResultIndex, conversionContextResultRegister, identifierRegister - ) + val freeRegister = findFreeRegister(insertIndex) + val identifierRegister = findFreeRegister(insertIndex, freeRegister) + val pathRegister = findFreeRegister(insertIndex, freeRegister, identifierRegister) - // Check if the component should be filtered, and save the result to a thread local. addInstructionsAtControlFlowLabel( - conversionContextResultIndex + 1, + insertIndex, """ - iget-object v$identifierRegister, v$conversionContextResultRegister, $conversionContextIdentifierField - iget-object v$stringBuilderRegister, v$conversionContextResultRegister, $conversionContextPathBuilderField - invoke-static { v$identifierRegister, v$stringBuilderRegister }, $EXTENSION_CLASS_DESCRIPTOR->filter(Ljava/lang/String;Ljava/lang/StringBuilder;)V + move-object/from16 v$freeRegister, p2 + iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField + iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField + invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->shouldFilter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z + move-result v$freeRegister + if-eqz v$freeRegister, :unfiltered + + # Return an empty component + move-object/from16 v$freeRegister, p1 + invoke-static { v$freeRegister }, $builderMethodDescriptor + move-result-object v$freeRegister + iget-object v$freeRegister, v$freeRegister, $emptyComponentField + return-object v$freeRegister + + :unfiltered + nop """ ) - - // Get the only static method in the class. - val builderMethodDescriptor = emptyComponentFingerprint.classDef.methods.single { - method -> AccessFlags.STATIC.isSet(method.accessFlags) - } - // Only one field. - val emptyComponentField = classBy { classDef -> - classDef.type == builderMethodDescriptor.returnType - }!!.immutableClass.fields.single() - - // Check at each return value if the component is filtered, - // and return an empty component if filtering is needed. - findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { returnIndex -> - val freeRegister = findFreeRegister(returnIndex) - - addInstructionsAtControlFlowLabel( - returnIndex, - """ - invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->shouldFilter()Z - move-result v$freeRegister - if-eqz v$freeRegister, :unfiltered - - move-object/from16 v$freeRegister, p1 - invoke-static { v$freeRegister }, $builderMethodDescriptor - move-result-object v$freeRegister - iget-object v$freeRegister, v$freeRegister, $emptyComponentField - return-object v$freeRegister - - :unfiltered - nop - """ - ) - } } // endregion @@ -233,23 +211,23 @@ val lithoFilterPatch = bytecodePatch( // Flag was removed in 20.05. It appears a new flag might be used instead (45660109L), // but if the flag is forced on then litho filtering still works correctly. if (is_19_25_or_greater && !is_20_05_or_greater) { - lithoComponentNameUpbFeatureFlagFingerprint.method.apply { - // Don't use return early, so the debug patch logs if this was originally on. - val insertIndex = indexOfFirstInstructionOrThrow(Opcode.RETURN) - val register = getInstruction(insertIndex).registerA - - addInstruction(insertIndex, "const/4 v$register, 0x0") - } + lithoComponentNameUpbFeatureFlagFingerprint.method.returnLate(false) } // Turn off a feature flag that enables native code of protobuf parsing (Upb protobuf). - // If this is enabled, then the litho protobuffer hook will always show an empty buffer - // since it's no longer handled by the hooked Java code. - lithoConverterBufferUpbFeatureFlagFingerprint.method.apply { - val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) - val register = getInstruction(index).registerA + lithoConverterBufferUpbFeatureFlagFingerprint.let { + // FIXME: Procool buffer has changed in 20.22, and UPB native code is now always enabled. + if (is_20_22_or_greater) { + Logger.getLogger(this::class.java.name).severe( + "\n!!!\n!!! Litho filtering does not yet support 20.22+ Many UI components will not be hidden.\n!!!") + } - addInstruction(index + 1, "const/4 v$register, 0x0") + // 20.22 the flag is still enabled in one location, but what it does is not clear. + // Disable it anyway. + it.method.insertLiteralOverride( + it.instructionMatches.first().index, + false + ) } // endregion @@ -258,4 +236,4 @@ val lithoFilterPatch = bytecodePatch( finalize { lithoFilterFingerprint.method.replaceInstruction(0, "const/16 v0, $filterCount") } -} +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt index a5fa0ed5e2..2ba5de2bc6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt @@ -1,30 +1,36 @@ package app.revanced.patches.youtube.misc.navigation +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import app.revanced.patches.youtube.layout.buttons.navigation.navigationButtonsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import app.revanced.util.literal 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 actionBarSearchResultsFingerprint = fingerprint { +internal val actionBarSearchResultsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") - literal { actionBarSearchResultsViewMicId } + instructions( + resourceLiteral("layout", "action_bar_search_results_view_mic"), + methodCall(name = "setLayoutDirection") + ) } -internal val toolbarLayoutFingerprint = fingerprint { +internal val toolbarLayoutFingerprint by fingerprint { accessFlags(AccessFlags.PROTECTED, AccessFlags.CONSTRUCTOR) - literal { toolbarContainerId } + instructions( + resourceLiteral("id", "toolbar_container"), + checkCast("Lcom/google/android/apps/youtube/app/ui/actionbar/MainCollapsingToolbarLayout;") + ) } /** * Matches to https://android.googlesource.com/platform/frameworks/support/+/9eee6ba/v7/appcompat/src/android/support/v7/widget/Toolbar.java#963 */ -internal val appCompatToolbarBackButtonFingerprint = fingerprint { +internal val appCompatToolbarBackButtonFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/graphics/drawable/Drawable;") parameters() @@ -36,17 +42,19 @@ internal val appCompatToolbarBackButtonFingerprint = fingerprint { /** * Matches to the class found in [pivotBarConstructorFingerprint]. */ -internal val initializeButtonsFingerprint = fingerprint { +internal val initializeButtonsFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") - literal { imageOnlyTabResourceId } + instructions( + resourceLiteral("layout", "image_only_tab") + ) } /** * Extension method, used for callback into to other patches. * Specifically, [navigationButtonsPatch]. */ -internal val navigationBarHookCallbackFingerprint = fingerprint { +internal val navigationBarHookCallbackFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("V") parameters(EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR, "Landroid/view/View;") @@ -59,7 +67,7 @@ internal val navigationBarHookCallbackFingerprint = fingerprint { /** * Matches to the Enum class that looks up ordinal -> instance. */ -internal val navigationEnumFingerprint = fingerprint { +internal val navigationEnumFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) strings( "PIVOT_HOME", @@ -72,17 +80,17 @@ internal val navigationEnumFingerprint = fingerprint { ) } -internal val pivotBarButtonsCreateDrawableViewFingerprint = fingerprint { +internal val pivotBarButtonsCreateDrawableViewFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") custom { method, _ -> method.definingClass == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" && - // Only one method has a Drawable parameter. + // Only one view creation method has a Drawable parameter. method.parameterTypes.firstOrNull() == "Landroid/graphics/drawable/Drawable;" } } -internal val pivotBarButtonsCreateResourceViewFingerprint = fingerprint { +internal val pivotBarButtonsCreateResourceStyledViewFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") parameters("L", "Z", "I", "L") @@ -91,33 +99,49 @@ internal val pivotBarButtonsCreateResourceViewFingerprint = fingerprint { } } -internal fun indexOfSetViewSelectedInstruction(method: Method) = method.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setSelected" +/** + * 20.21+ + */ +internal val pivotBarButtonsCreateResourceIntViewFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Landroid/view/View;") + custom { method, _ -> + method.definingClass == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" && + // Only one view creation method has an int first parameter. + method.parameterTypes.firstOrNull() == "I" + } } -internal val pivotBarButtonsViewSetSelectedFingerprint = fingerprint { +internal val pivotBarButtonsViewSetSelectedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("I", "Z") + instructions( + methodCall(name = "setSelected") + ) custom { method, _ -> - indexOfSetViewSelectedInstruction(method) >= 0 && - method.definingClass == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" + method.definingClass == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" } } -internal val pivotBarConstructorFingerprint = fingerprint { +internal val pivotBarConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - strings("com.google.android.apps.youtube.app.endpoint.flags") + instructions( + string("com.google.android.apps.youtube.app.endpoint.flags"), + ) } -internal val imageEnumConstructorFingerprint = fingerprint { +internal val imageEnumConstructorFingerprint by fingerprint { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - strings("TAB_ACTIVITY_CAIRO") + instructions( + string("TAB_ACTIVITY_CAIRO"), + opcode(Opcode.SPUT_OBJECT) + ) } -internal val setEnumMapFingerprint = fingerprint { +internal val setEnumMapFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - literal { - ytFillBellId - } + instructions( + resourceLiteral("drawable", "yt_fill_bell_black_24") + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt index f1ea33327b..7ee74c86d1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -6,20 +6,17 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.instructions import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater +import app.revanced.patches.youtube.misc.playservice.is_20_21_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.shared.mainActivityOnBackPressedFingerprint import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow -import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation @@ -28,30 +25,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.TypeReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.util.MethodUtil -internal var imageOnlyTabResourceId = -1L - private set -internal var actionBarSearchResultsViewMicId = -1L - private set -internal var ytFillBellId = -1L - private set -internal var toolbarContainerId = -1L - private set - -private val navigationBarHookResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - imageOnlyTabResourceId = resourceMappings["layout", "image_only_tab"] - actionBarSearchResultsViewMicId = resourceMappings["layout", "action_bar_search_results_view_mic"] - ytFillBellId = resourceMappings["drawable", "yt_fill_bell_black_24"] - toolbarContainerId = resourceMappings["id", "toolbar_container"] - } -} - internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/shared/NavigationBar;" internal const val EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR = @@ -64,12 +40,13 @@ lateinit var hookNavigationButtonCreated: (String) -> Unit val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navigation or search bar.") { dependsOn( sharedExtensionPatch, - navigationBarHookResourcePatch, + versionCheckPatch, playerTypeHookPatch, // Required to detect the search bar in all situations. + resourceMappingPatch, // Used by fingerprints ) execute { - fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) { + fun MutableMethod.addHook(hook: NavigationHook, insertPredicate: Instruction.() -> Boolean) { val filtered = instructions.filter(insertPredicate) if (filtered.isEmpty()) throw PatchException("Could not find insert indexes") filtered.forEach { @@ -87,22 +64,32 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig initializeButtonsFingerprint.match(pivotBarConstructorFingerprint.originalClassDef).method.apply { // Hook the current navigation bar enum value. Note, the 'You' tab does not have an enum value. val navigationEnumClassName = navigationEnumFingerprint.classDef.type - addHook(Hook.SET_LAST_APP_NAVIGATION_ENUM) { + addHook(NavigationHook.SET_LAST_APP_NAVIGATION_ENUM) { opcode == Opcode.INVOKE_STATIC && getReference()?.definingClass == navigationEnumClassName } // Hook the creation of navigation tab views. val drawableTabMethod = pivotBarButtonsCreateDrawableViewFingerprint.method - addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{ + addHook(NavigationHook.NAVIGATION_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( getReference() ?: return@predicate false, drawableTabMethod, ) } - val imageResourceTabMethod = pivotBarButtonsCreateResourceViewFingerprint.originalMethod - addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{ + if (is_20_21_or_greater) { + val imageResourceIntTabMethod = pivotBarButtonsCreateResourceIntViewFingerprint.originalMethod + addHook(NavigationHook.NAVIGATION_TAB_LOADED) predicate@{ + MethodUtil.methodSignaturesMatch( + getReference() ?: return@predicate false, + imageResourceIntTabMethod, + ) + } + } + + val imageResourceTabMethod = pivotBarButtonsCreateResourceStyledViewFingerprint.originalMethod + addHook(NavigationHook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( getReference() ?: return@predicate false, imageResourceTabMethod, @@ -110,17 +97,19 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig } } - pivotBarButtonsViewSetSelectedFingerprint.method.apply { - val index = indexOfSetViewSelectedInstruction(this) - val instruction = getInstruction(index) - val viewRegister = instruction.registerC - val isSelectedRegister = instruction.registerD + pivotBarButtonsViewSetSelectedFingerprint.let { + it.method.apply { + val index = it.instructionMatches.first().index + val instruction = getInstruction(index) + val viewRegister = instruction.registerC + val isSelectedRegister = instruction.registerD - addInstruction( - index + 1, - "invoke-static { v$viewRegister, v$isSelectedRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;Z)V", - ) + addInstruction( + index + 1, + "invoke-static { v$viewRegister, v$isSelectedRegister }, " + + "$EXTENSION_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;Z)V", + ) + } } // Hook onto back button pressed. Needed to fix race problem with @@ -136,37 +125,31 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig // Two different layouts are used at the hooked code. // Insert before the first ViewGroup method call after inflating, // so this works regardless which layout is used. - actionBarSearchResultsFingerprint.method.apply { - val searchBarResourceId = indexOfFirstLiteralInstructionOrThrow( - actionBarSearchResultsViewMicId, - ) + actionBarSearchResultsFingerprint.let { + it.method.apply { + val instructionIndex = it.instructionMatches.last().index + val viewRegister = getInstruction(instructionIndex).registerC - val instructionIndex = indexOfFirstInstructionOrThrow(searchBarResourceId) { - opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setLayoutDirection" + addInstruction( + instructionIndex, + "invoke-static { v$viewRegister }, " + + "$EXTENSION_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V", + ) } - - val viewRegister = getInstruction(instructionIndex).registerC - - addInstruction( - instructionIndex, - "invoke-static { v$viewRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V", - ) } // Hook the back button visibility. - toolbarLayoutFingerprint.method.apply { - val index = indexOfFirstInstructionOrThrow { - opcode == Opcode.CHECK_CAST && getReference()?.type == - "Lcom/google/android/apps/youtube/app/ui/actionbar/MainCollapsingToolbarLayout;" - } - val register = getInstruction(index).registerA + toolbarLayoutFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA - addInstruction( - index + 1, - "invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->setToolbar(Landroid/widget/FrameLayout;)V" - ) + addInstruction( + index + 1, + "invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->setToolbar(Landroid/widget/FrameLayout;)V" + ) + } } // Add interface for extensions code to call obfuscated methods. @@ -212,13 +195,8 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig // Fix YT bug of notification tab missing the filled icon. if (is_19_35_or_greater) { - val cairoNotificationEnumReference = with(imageEnumConstructorFingerprint) { - val stringIndex = stringMatches!!.first().index - val cairoNotificationEnumIndex = method.indexOfFirstInstructionOrThrow(stringIndex) { - opcode == Opcode.SPUT_OBJECT - } - method.getInstruction(cairoNotificationEnumIndex).reference - } + val cairoNotificationEnumReference = imageEnumConstructorFingerprint + .instructionMatches.last().getInstruction().reference setEnumMapFingerprint.method.apply { val enumMapIndex = indexOfFirstInstructionReversedOrThrow { @@ -242,7 +220,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig } } -private enum class Hook(val methodName: String, val parameters: String) { +private enum class NavigationHook(val methodName: String, val parameters: String) { SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"), NAVIGATION_TAB_LOADED("navigationTabLoaded", "Landroid/view/View;"), NAVIGATION_IMAGE_RESOURCE_TAB_LOADED("navigationImageResourceTabLoaded", "Landroid/view/View;"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt index 95dbd54ecb..10fb649a69 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt @@ -1,18 +1,15 @@ package app.revanced.patches.youtube.misc.playercontrols +import app.revanced.patcher.checkCast import app.revanced.patcher.fingerprint -import app.revanced.util.containsLiteralInstruction -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal val playerTopControlsInflateFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("V") - parameters() - literal { controlsLayoutStub } -} - -internal val playerControlsExtensionHookListenersExistFingerprint = fingerprint { +internal val playerControlsExtensionHookListenersExistFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Z") parameters() @@ -22,7 +19,7 @@ internal val playerControlsExtensionHookListenersExistFingerprint = fingerprint } } -internal val playerControlsExtensionHookFingerprint = fingerprint { +internal val playerControlsExtensionHookFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("V") parameters("Z") @@ -32,42 +29,62 @@ internal val playerControlsExtensionHookFingerprint = fingerprint { } } -internal val playerBottomControlsInflateFingerprint = fingerprint { +internal val playerTopControlsInflateFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("V") + parameters() + instructions( + resourceLiteral("id", "controls_layout_stub"), + methodCall("Landroid/view/ViewStub;", "inflate"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) + ) +} + +internal val playerBottomControlsInflateFingerprint by fingerprint { returns("Ljava/lang/Object;") parameters() - literal { bottomUiContainerResourceId } + instructions( + resourceLiteral("id", "bottom_ui_container_stub"), + methodCall("Landroid/view/ViewStub;", "inflate"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0) + ) } -internal val overlayViewInflateFingerprint = fingerprint { +internal val overlayViewInflateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/view/View;") - custom { methodDef, _ -> - methodDef.containsLiteralInstruction(fullscreenButton) && - methodDef.containsLiteralInstruction(heatseekerViewstub) - } + instructions( + resourceLiteral("id", "heatseeker_viewstub"), + resourceLiteral("id", "fullscreen_button"), + checkCast("Landroid/widget/ImageView;") + ) } /** * Resolves to the class found in [playerTopControlsInflateFingerprint]. */ -internal val controlsOverlayVisibilityFingerprint = fingerprint { +internal val controlsOverlayVisibilityFingerprint by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("V") parameters("Z", "Z") } -internal val playerBottomControlsExploderFeatureFlagFingerprint = fingerprint { +internal val playerBottomControlsExploderFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters() - literal { 45643739L } + instructions( + literal(45643739L) + ) } -internal val playerTopControlsExperimentalLayoutFeatureFlagFingerprint = fingerprint { +internal val playerTopControlsExperimentalLayoutFeatureFlagFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("I") parameters() - literal { 45629424L } + instructions( + literal(45629424L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt index 7db8de5b2b..6059564f6c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt @@ -8,17 +8,19 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.Document import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater -import app.revanced.util.* +import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater +import app.revanced.util.copyXmlNode +import app.revanced.util.findElementByAttributeValue +import app.revanced.util.findElementByAttributeValueOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.inputStreamFromBundledResource +import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.TypeReference import org.w3c.dom.Node /** @@ -40,18 +42,7 @@ internal lateinit var addTopControl: (String) -> Unit lateinit var addBottomControl: (String) -> Unit private set -internal var bottomUiContainerResourceId = -1L - private set -internal var controlsLayoutStub = -1L - private set -internal var heatseekerViewstub = -1L - private set -internal var fullscreenButton = -1L - private set - val playerControlsResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - /** * The element to the left of the element being added. */ @@ -65,11 +56,6 @@ val playerControlsResourcePatch = resourcePatch { execute { val targetResourceName = "youtube_controls_bottom_ui_container.xml" - bottomUiContainerResourceId = resourceMappings["id", "bottom_ui_container_stub"] - controlsLayoutStub = resourceMappings["id", "controls_layout_stub"] - heatseekerViewstub = resourceMappings["id", "heatseeker_viewstub"] - fullscreenButton = resourceMappings["id", "fullscreen_button"] - bottomTargetDocument = document("res/layout/$targetResourceName") val bottomTargetElement: Node = bottomTargetDocument.getElementsByTagName( @@ -226,29 +212,28 @@ val playerControlsPatch = bytecodePatch( dependsOn( playerControlsResourcePatch, sharedExtensionPatch, + resourceMappingPatch // Used by fingerprints. ) execute { - fun MutableMethod.indexOfFirstViewInflateOrThrow() = indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.definingClass == "Landroid/view/ViewStub;" && - reference.name == "inflate" - } + playerBottomControlsInflateFingerprint.let { + it.method.apply { + inflateBottomControlMethod = this - playerBottomControlsInflateFingerprint.method.apply { - inflateBottomControlMethod = this - - val inflateReturnObjectIndex = indexOfFirstViewInflateOrThrow() + 1 - inflateBottomControlRegister = getInstruction(inflateReturnObjectIndex).registerA - inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1 + val inflateReturnObjectIndex = it.instructionMatches.last().index + inflateBottomControlRegister = getInstruction(inflateReturnObjectIndex).registerA + inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1 + } } - playerTopControlsInflateFingerprint.method.apply { - inflateTopControlMethod = this + playerTopControlsInflateFingerprint.let { + it.method.apply { + inflateTopControlMethod = this - val inflateReturnObjectIndex = indexOfFirstViewInflateOrThrow() + 1 - inflateTopControlRegister = getInstruction(inflateReturnObjectIndex).registerA - inflateTopControlInsertIndex = inflateReturnObjectIndex + 1 + val inflateReturnObjectIndex = it.instructionMatches.last().index + inflateTopControlRegister = getInstruction(inflateReturnObjectIndex).registerA + inflateTopControlInsertIndex = inflateReturnObjectIndex + 1 + } } visibilityMethod = controlsOverlayVisibilityFingerprint.match( @@ -257,21 +242,17 @@ val playerControlsPatch = bytecodePatch( // Hook the fullscreen close button. Used to fix visibility // when seeking and other situations. - overlayViewInflateFingerprint.method.apply { - val resourceIndex = indexOfFirstLiteralInstructionReversedOrThrow(fullscreenButton) + overlayViewInflateFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA - val index = indexOfFirstInstructionOrThrow(resourceIndex) { - opcode == Opcode.CHECK_CAST && - getReference()?.type == - "Landroid/widget/ImageView;" + addInstruction( + index + 1, + "invoke-static { v$register }, " + + "$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V", + ) } - val register = getInstruction(index).registerA - - addInstruction( - index + 1, - "invoke-static { v$register }, " + - "$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V", - ) } visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistFingerprint.method @@ -285,7 +266,7 @@ val playerControlsPatch = bytecodePatch( playerBottomControlsExploderFeatureFlagFingerprint.method.returnEarly() } - // A/B test of new top overlay controls. Two different layouts can be used: + // A/B test of different top overlay controls. Two different layouts can be used: // youtube_cf_navigation_improvement_controls_layout.xml // youtube_cf_minimal_impact_controls_layout.xml // @@ -294,18 +275,14 @@ val playerControlsPatch = bytecodePatch( // is active, but what it does is not entirely clear. // // For now force this a/b feature off as it breaks the top player buttons. - if (is_19_25_or_greater) { + // + // Edit: Flag appears to be removed in 20.19 + if (is_19_25_or_greater && !is_20_19_or_greater) { playerTopControlsExperimentalLayoutFeatureFlagFingerprint.method.apply { val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_OBJECT) val register = getInstruction(index).registerA - addInstructions( - index + 1, - """ - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerTopControlsLayoutResourceName(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$register - """, - ) + addInstruction(index + 1, "const-string v$register, \"default\"") } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt index 522d06b204..510abc45a1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.youtube.misc.playertype import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val playerTypeFingerprint = fingerprint { +internal val playerTypeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") @@ -16,20 +17,24 @@ internal val playerTypeFingerprint = fingerprint { custom { _, classDef -> classDef.endsWith("/YouTubePlayerOverlaysLayout;") } } -internal val reelWatchPagerFingerprint = fingerprint { +internal val reelWatchPagerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Landroid/view/View;") - literal { reelWatchPlayerId } + instructions( + resourceLiteral("id", "reel_watch_player"), + opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 10) + ) } -internal val videoStateFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("V") - parameters("Lcom/google/android/libraries/youtube/player/features/overlay/controls/ControlsState;") - opcodes( - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, // obfuscated parameter field name +internal val videoStateEnumFingerprint by fingerprint { + accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) + parameters() + strings( + "NEW", + "PLAYING", + "PAUSED", + "RECOVERABLE_ERROR", + "UNRECOVERABLE_ERROR", + "ENDED" ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt index b14de0cbea..2655844f7f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt @@ -3,35 +3,22 @@ package app.revanced.patches.youtube.misc.playertype 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.fieldAccess +import app.revanced.patcher.fingerprint +import app.revanced.patcher.literal import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstLiteralInstructionOrThrow -import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/PlayerTypeHookPatch;" -internal var reelWatchPlayerId = -1L - private set - -private val playerTypeHookResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - reelWatchPlayerId = resourceMappings["id", "reel_watch_player"] - } -} - val playerTypeHookPatch = bytecodePatch( description = "Hook to get the current player type and video playback state.", ) { - dependsOn(sharedExtensionPatch, playerTypeHookResourcePatch) + dependsOn(sharedExtensionPatch, resourceMappingPatch) execute { playerTypeFingerprint.method.addInstruction( @@ -39,28 +26,48 @@ val playerTypeHookPatch = bytecodePatch( "invoke-static {p1}, $EXTENSION_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V", ) - reelWatchPagerFingerprint.method.apply { - val literalIndex = indexOfFirstLiteralInstructionOrThrow(reelWatchPlayerId) - val registerIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT) - val viewRegister = getInstruction(registerIndex).registerA + reelWatchPagerFingerprint.let { + it.method.apply { + val index = it.instructionMatches.last().index + val register = getInstruction(index).registerA + + addInstruction( + index + 1, + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V" + ) + } + } - addInstruction( - registerIndex + 1, - "invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V" + val videoStateFingerprint by fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("V") + parameters("Lcom/google/android/libraries/youtube/player/features/overlay/controls/ControlsState;") + instructions( + literal(1), + literal(literal = 0, maxAfter = 10), + // Obfuscated parameter field name. + fieldAccess( + definingClass = { "Lcom/google/android/libraries/youtube/player/features/overlay/controls/ControlsState;"}, + type = { videoStateEnumFingerprint.originalClassDef.type }, + maxAfter = 5 + ) ) } - videoStateFingerprint.method.apply { - val endIndex = videoStateFingerprint.patternMatch!!.endIndex - val videoStateFieldName = getInstruction(endIndex).reference + videoStateFingerprint.let { + it.method.apply { + val videoStateFieldName = getInstruction( + it.instructionMatches.last().index + ).reference - addInstructions( - 0, - """ - iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field - invoke-static {v0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V - """ - ) + addInstructions( + 0, + """ + iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field + invoke-static {v0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V + """ + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt index 4b29ca62c7..e37782033e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt @@ -5,15 +5,6 @@ package app.revanced.patches.youtube.misc.playservice import app.revanced.patcher.patch.resourcePatch import app.revanced.util.findElementByAttributeValueOrThrow -@Deprecated("19.34.42 is the lowest supported version") -var is_19_03_or_greater = false - private set -@Deprecated("19.34.42 is the lowest supported version") -var is_19_04_or_greater = false - private set -@Deprecated("19.34.42 is the lowest supported version") -var is_19_16_or_greater = false - private set @Deprecated("19.34.42 is the lowest supported version") var is_19_17_or_greater = false private set @@ -70,6 +61,14 @@ var is_20_14_or_greater = false private set var is_20_15_or_greater = false private set +var is_20_19_or_greater = false + private set +var is_20_20_or_greater = false + private set +var is_20_21_or_greater = false + private set +var is_20_22_or_greater = false + private set val versionCheckPatch = resourcePatch( description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.", @@ -85,9 +84,6 @@ val versionCheckPatch = resourcePatch( } // All bug fix releases always seem to use the same play store version as the minor version. - is_19_03_or_greater = 240402000 <= playStoreServicesVersion - is_19_04_or_greater = 240502000 <= playStoreServicesVersion - is_19_16_or_greater = 241702000 <= playStoreServicesVersion is_19_17_or_greater = 241802000 <= playStoreServicesVersion is_19_18_or_greater = 241902000 <= playStoreServicesVersion is_19_23_or_greater = 242402000 <= playStoreServicesVersion @@ -112,5 +108,9 @@ val versionCheckPatch = resourcePatch( is_20_10_or_greater = 251105000 <= playStoreServicesVersion is_20_14_or_greater = 251505000 <= playStoreServicesVersion is_20_15_or_greater = 251605000 <= playStoreServicesVersion + is_20_19_or_greater = 252005000 <= playStoreServicesVersion + is_20_20_or_greater = 252105000 <= playStoreServicesVersion + is_20_21_or_greater = 252205000 <= playStoreServicesVersion + is_20_22_or_greater = 252305000 <= playStoreServicesVersion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/Fingerprints.kt index 72734bba70..7e9e67a285 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/Fingerprints.kt @@ -4,7 +4,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags import app.revanced.patcher.fingerprint -internal val copyTextFingerprint = fingerprint { +internal val copyTextFingerprint by fingerprint { returns("V") parameters("L", "Ljava/util/Map;") opcodes( @@ -21,7 +21,7 @@ internal val copyTextFingerprint = fingerprint { strings("text/plain") } -internal val systemShareSheetFingerprint = fingerprint { +internal val systemShareSheetFingerprint by fingerprint { returns("V") parameters("L", "Ljava/util/Map;") opcodes( @@ -31,7 +31,7 @@ internal val systemShareSheetFingerprint = fingerprint { strings("YTShare_Logging_Share_Intent_Endpoint_Byte_Array") } -internal val youtubeShareSheetFingerprint = fingerprint { +internal val youtubeShareSheetFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "Ljava/util/Map;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt index 9c96159ae7..9a388d3f21 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt @@ -49,7 +49,7 @@ val removeTrackingQueryParameterPatch = bytecodePatch( getInsertIndex: Match.PatternMatch.() -> Int, getUrlRegister: MutableMethod.(insertIndex: Int) -> Int, ) { - val insertIndex = patternMatch!!.getInsertIndex() + val insertIndex = patternMatch.getInsertIndex() val urlRegister = method.getUrlRegister(insertIndex) method.addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt index 09aa7bf4cd..a2bf2ee303 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt @@ -4,9 +4,8 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val recyclerViewTreeObserverFingerprint = fingerprint { +internal val recyclerViewTreeObserverFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") opcodes( Opcode.CHECK_CAST, Opcode.NEW_INSTANCE, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt index 86588df099..1044c7d2f2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt @@ -13,7 +13,7 @@ val recyclerViewTreeHookPatch = bytecodePatch { execute { recyclerViewTreeObserverFingerprint.method.apply { - val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1 + val insertIndex = recyclerViewTreeObserverFingerprint.instructionMatches.first().index + 1 val recyclerViewParameter = 2 addRecyclerViewTreeHook = { classDescriptor -> diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt index 3dd3816b52..e9df45bad9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt @@ -1,29 +1,35 @@ package app.revanced.patches.youtube.misc.settings import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.opcode +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -internal val licenseActivityOnCreateFingerprint = fingerprint { +internal val licenseActivityOnCreateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") - parameters("L") + parameters("Landroid/os/Bundle;") custom { method, classDef -> - classDef.endsWith("LicenseActivity;") && method.name == "onCreate" + method.name == "onCreate" && classDef.endsWith("/LicenseActivity;") } } -internal val setThemeFingerprint = fingerprint { +internal val setThemeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters() - literal { appearanceStringId } + instructions( + resourceLiteral("string", "app_theme_appearance_dark"), + ) } -internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L - -internal val cairoFragmentConfigFingerprint = fingerprint { +internal val cairoFragmentConfigFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") - literal { CAIRO_CONFIG_LITERAL_VALUE } -} + instructions( + literal(45532100L), + opcode(Opcode.MOVE_RESULT, 10) + ) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt index fce41f3275..6383779cf6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt @@ -8,9 +8,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.overrideThemeColors import app.revanced.patches.shared.misc.settings.preference.BasePreference import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen @@ -48,9 +46,6 @@ import com.android.tools.smali.dexlib2.util.MethodUtil private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/settings/LicenseActivityHook;" -internal var appearanceStringId = -1L - private set - private val preferences = mutableSetOf() fun addSettingPreference(screen: BasePreference) { @@ -86,8 +81,6 @@ private val settingsResourcePatch = resourcePatch { ) execute { - appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"] - // Use same colors as stock YouTube. overrideThemeColors("@color/yt_white1", "@color/yt_black3") @@ -228,14 +221,19 @@ val settingsPatch = bytecodePatch( // Modify the license activity and remove all existing layout code. // Must modify an existing activity and cannot add a new activity to the manifest, // as that fails for root installations. - - licenseActivityOnCreateFingerprint.method.addInstructions( - 1, - """ - invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->initialize(Landroid/app/Activity;)V - return-void - """ - ) + licenseActivityOnCreateFingerprint.let { + val superClass = it.classDef.superclass + + it.method.addInstructions( + 0, + """ + # Some targets have extra instructions before the call to super method. + invoke-super { p0, p1 }, $superClass->onCreate(Landroid/os/Bundle;)V + invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->initialize(Landroid/app/Activity;)V + return-void + """ + ) + } // Remove other methods as they will break as the onCreate method is modified above. licenseActivityOnCreateFingerprint.classDef.apply { @@ -281,11 +279,13 @@ val settingsPatch = bytecodePatch( } // Add setting to force cairo settings fragment on/off. - cairoFragmentConfigFingerprint.method.insertLiteralOverride( - CAIRO_CONFIG_LITERAL_VALUE, - "$EXTENSION_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z" - ) - } + cairoFragmentConfigFingerprint.let { + it.method.insertLiteralOverride( + it.instructionMatches.last().index, + "$EXTENSION_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z" + ) + } + } finalize { PreferenceScreen.close() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt deleted file mode 100644 index 44cde6002b..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.patches.youtube.misc.zoomhaptics - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.youtube.misc.hapticfeedback.disableHapticFeedbackPatch - -@Deprecated("Superseded by disableHapticFeedbackPatch", ReplaceWith("disableHapticFeedbackPatch")) -val zoomHapticsPatch = bytecodePatch( - description = "Adds an option to disable haptics when zooming.", -) { - dependsOn(disableHapticFeedbackPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index 82eb0f7a94..78f311a700 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -1,10 +1,17 @@ package app.revanced.patches.youtube.shared +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.newInstance +import app.revanced.patcher.opcode +import app.revanced.patcher.string +import app.revanced.patches.shared.misc.mapping.resourceLiteral import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val conversionContextFingerprintToString = fingerprint { +internal val conversionContextFingerprintToString by fingerprint { parameters() strings( "ConversionContext{containerInternal=", @@ -19,7 +26,7 @@ internal val conversionContextFingerprintToString = fingerprint { } } -internal val autoRepeatFingerprint = fingerprint { +internal val autoRepeatFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() @@ -28,23 +35,27 @@ internal val autoRepeatFingerprint = fingerprint { } } -internal val autoRepeatParentFingerprint = fingerprint { +internal val autoRepeatParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") - strings( - "play() called when the player wasn't loaded.", - "play() blocked because Background Playability failed", + instructions( + string("play() called when the player wasn't loaded."), + string("play() blocked because Background Playability failed") ) } -internal val layoutConstructorFingerprint = fingerprint { +internal val layoutConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") - parameters() - strings("1.0x") + instructions( + literal(159962), + resourceLiteral("id", "player_control_previous_button_touch_area"), + resourceLiteral("id", "player_control_next_button_touch_area"), + methodCall(parameters = listOf("Landroid/view/View;", "I")) + ) } -internal val mainActivityConstructorFingerprint = fingerprint { +internal val mainActivityConstructorFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameters() custom { _, classDef -> @@ -52,7 +63,7 @@ internal val mainActivityConstructorFingerprint = fingerprint { } } -internal val mainActivityOnBackPressedFingerprint = fingerprint { +internal val mainActivityOnBackPressedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters() @@ -61,7 +72,7 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint { } } -internal val mainActivityOnCreateFingerprint = fingerprint { +internal val mainActivityOnCreateFingerprint by fingerprint { returns("V") parameters("Landroid/os/Bundle;") custom { method, classDef -> @@ -69,7 +80,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint { } } -internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint { +internal val rollingNumberTextViewAnimationUpdateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/graphics/Bitmap;") @@ -95,16 +106,25 @@ internal val rollingNumberTextViewAnimationUpdateFingerprint = fingerprint { } } -internal val seekbarFingerprint = fingerprint { +internal val seekbarFingerprint by fingerprint { returns("V") - strings("timed_markers_width") + instructions( + string("timed_markers_width"), + ) } -internal val seekbarOnDrawFingerprint = fingerprint { +/** + * Matches to _mutable_ class found in [seekbarFingerprint]. + */ +internal val seekbarOnDrawFingerprint by fingerprint { + instructions( + methodCall(smali = "Ljava/lang/Math;->round(F)I"), + opcode(Opcode.MOVE_RESULT, maxAfter = 0) + ) custom { method, _ -> method.name == "onDraw" } } -internal val subtitleButtonControllerFingerprint = fingerprint { +internal val subtitleButtonControllerFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;") @@ -121,28 +141,14 @@ internal val subtitleButtonControllerFingerprint = fingerprint { ) } -internal val newVideoQualityChangedFingerprint = fingerprint { +internal val newVideoQualityChangedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("L") - opcodes( - Opcode.IGET, // Video resolution (human readable). - Opcode.IGET_OBJECT, - Opcode.IGET_BOOLEAN, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET, + instructions( + newInstance("Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"), + opcode(Opcode.IGET_OBJECT), + opcode(Opcode.CHECK_CAST), + fieldAccess(type = "I", opcode = Opcode.IGET, maxAfter = 0), // Video resolution (human readable). ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt index a338ea6b7d..16dbc07f73 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/Fingerprints.kt @@ -1,23 +1,30 @@ package app.revanced.patches.youtube.video.audio import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -internal val streamingModelBuilderFingerprint = fingerprint { +internal val streamingModelBuilderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") - strings("vprng") + instructions( + string("vprng") + ) } -internal val menuItemAudioTrackFingerprint = fingerprint { +internal val menuItemAudioTrackFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameters("L") returns("V") - strings("menu_item_audio_track") + instructions( + string("menu_item_audio_track") + ) } -internal val audioStreamingTypeSelector = fingerprint { +internal val audioStreamingTypeSelector by fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returns("L") - strings("raw") // String is not unique + instructions( + string("raw") // String is not unique + ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt index 72fbce7930..450179ff85 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt @@ -77,9 +77,7 @@ val forceOriginalAudioPatch = bytecodePatch( val isDefaultMethod = streamingModelBuilderFingerprint.originalMethod.firstFormatStreamingModelCall("Z") val audioTrackIdMethod = menuItemAudioTrackFingerprint.originalMethod.firstFormatStreamingModelCall() val audioTrackDisplayNameMethod = audioStreamingTypeSelector.originalMethod.firstFormatStreamingModelCall() - val formatStreamModelClass = proxy(classes.first { - it.type == audioTrackIdMethod.definingClass - }).mutableClass + val formatStreamModelClass = mutableClassBy(audioTrackIdMethod.definingClass) formatStreamModelClass.apply { // Add a new field to store the override. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/DisableHdrPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/DisableHdrPatch.kt index 954d8bae7b..7724c44f4b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/DisableHdrPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/DisableHdrPatch.kt @@ -8,9 +8,6 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/DisableHdrPatch;" @@ -45,14 +42,9 @@ val disableHdrPatch = bytecodePatch( hdrCapabilityFingerprint.let { it.originalMethod.apply { - val stringIndex = it.stringMatches!!.first().index - val navigateIndex = indexOfFirstInstructionOrThrow(stringIndex) { - val reference = getReference() - reference?.parameterTypes == listOf("I", "Landroid/view/Display;") && - reference.returnType == "Z" - } + val navigateIndex = it.instructionMatches.last().index - // Modify the HDR lookup method (Method is in the same class as the fingerprint). + // Modify the HDR lookup method (Method is in the same class as the fingerprint class). navigate(this).to(navigateIndex).stop().addInstructionsWithLabels( 0, """ diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/Fingerprints.kt index fe8d2dce3c..1dc39914de 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/hdr/Fingerprints.kt @@ -1,12 +1,15 @@ package app.revanced.patches.youtube.video.hdr import app.revanced.patcher.fingerprint +import app.revanced.patcher.methodCall +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -internal val hdrCapabilityFingerprint = fingerprint { +internal val hdrCapabilityFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - strings( - "av1_profile_main_10_hdr_10_plus_supported", - "video/av01" + instructions( + string("av1_profile_main_10_hdr_10_plus_supported"), + string("video/av01"), + methodCall(returnType = "Z", parameters = listOf("I", "Landroid/view/Display;")) ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt index 5157f9823e..4351309ceb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt @@ -1,18 +1,22 @@ package app.revanced.patches.youtube.video.information +import app.revanced.patcher.fieldAccess import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint import app.revanced.util.getReference import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.FieldReference -internal val createVideoPlayerSeekbarFingerprint = fingerprint { +internal val createVideoPlayerSeekbarFingerprint by fingerprint { returns("V") - strings("timed_markers_width") + instructions( + string("timed_markers_width"), + ) } -internal val onPlaybackSpeedItemClickFingerprint = fingerprint { +internal val onPlaybackSpeedItemClickFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L", "L", "I", "J") @@ -25,23 +29,27 @@ internal val onPlaybackSpeedItemClickFingerprint = fingerprint { } } -internal val playerControllerSetTimeReferenceFingerprint = fingerprint { +internal val playerControllerSetTimeReferenceFingerprint by fingerprint { opcodes(Opcode.INVOKE_DIRECT_RANGE, Opcode.IGET_OBJECT) strings("Media progress reported outside media playback: ") } -internal val playerInitFingerprint = fingerprint { - strings("playVideo called on player response with no videoStreamingData.") +internal val playerInitFingerprint by fingerprint { + instructions( + string("playVideo called on player response with no videoStreamingData."), + ) } /** * Matched using class found in [playerInitFingerprint]. */ -internal val seekFingerprint = fingerprint { - strings("Attempting to seek during an ad") +internal val seekFingerprint by fingerprint { + instructions( + string("Attempting to seek during an ad"), + ) } -internal val videoLengthFingerprint = fingerprint { +internal val videoLengthFingerprint by fingerprint { opcodes( Opcode.MOVE_RESULT_WIDE, Opcode.CMP_LONG, @@ -61,7 +69,7 @@ internal val videoLengthFingerprint = fingerprint { /** * Matches using class found in [mdxPlayerDirectorSetVideoStageFingerprint]. */ -internal val mdxSeekFingerprint = fingerprint { +internal val mdxSeekFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Z") parameters("J", "L") @@ -78,19 +86,20 @@ internal val mdxSeekFingerprint = fingerprint { } } -internal val mdxPlayerDirectorSetVideoStageFingerprint = fingerprint { - strings("MdxDirector setVideoStage ad should be null when videoStage is not an Ad state ") +internal val mdxPlayerDirectorSetVideoStageFingerprint by fingerprint { + instructions( + string("MdxDirector setVideoStage ad should be null when videoStage is not an Ad state "), + ) } /** * Matches using class found in [mdxPlayerDirectorSetVideoStageFingerprint]. */ -internal val mdxSeekRelativeFingerprint = fingerprint { +internal val mdxSeekRelativeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) // Return type is boolean up to 19.39, and void with 19.39+. parameters("J", "L") opcodes( - Opcode.IGET_OBJECT, Opcode.INVOKE_INTERFACE, ) @@ -99,7 +108,7 @@ internal val mdxSeekRelativeFingerprint = fingerprint { /** * Matches using class found in [playerInitFingerprint]. */ -internal val seekRelativeFingerprint = fingerprint { +internal val seekRelativeFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) // Return type is boolean up to 19.39, and void with 19.39+. parameters("J", "L") @@ -112,19 +121,16 @@ internal val seekRelativeFingerprint = fingerprint { /** * Resolves with the class found in [newVideoQualityChangedFingerprint]. */ -internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint { +internal val playbackSpeedMenuSpeedChangedFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("L") - opcodes( - Opcode.IGET, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.RETURN_OBJECT, + instructions( + fieldAccess(opcode = Opcode.IGET, type = "F") ) } -internal val playbackSpeedClassFingerprint = fingerprint { +internal val playbackSpeedClassFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returns("L") parameters("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 5a9c5e7406..e598ea22d4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -129,12 +129,12 @@ val videoInformationPatch = bytecodePatch( val videoLengthMethodMatch = videoLengthFingerprint.match(originalClassDef) videoLengthMethodMatch.method.apply { - val videoLengthRegisterIndex = videoLengthMethodMatch.patternMatch!!.endIndex - 2 + val videoLengthRegisterIndex = videoLengthMethodMatch.instructionMatches.last().index - 2 val videoLengthRegister = getInstruction(videoLengthRegisterIndex).registerA val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide addInstruction( - videoLengthMethodMatch.patternMatch!!.endIndex, + videoLengthMethodMatch.instructionMatches.last().index, "invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, " + "$EXTENSION_CLASS_DESCRIPTOR->setVideoLength(J)V", ) @@ -163,7 +163,7 @@ val videoInformationPatch = bytecodePatch( * Set the video time method */ timeMethod = navigate(playerControllerSetTimeReferenceFingerprint.originalMethod) - .to(playerControllerSetTimeReferenceFingerprint.patternMatch!!.startIndex) + .to(playerControllerSetTimeReferenceFingerprint.instructionMatches.first().index) .stop() /* @@ -190,8 +190,8 @@ val videoInformationPatch = bytecodePatch( getInstruction(indexOfFirstInstructionOrThrow(Opcode.IF_EQZ) - 1).reference as FieldReference setPlaybackSpeedMethod = - proxy(classes.first { it.type == setPlaybackSpeedMethodReference.definingClass }) - .mutableClass.methods.first { it.name == setPlaybackSpeedMethodReference.name } + mutableClassBy(setPlaybackSpeedMethodReference.definingClass) + .methods.first { it.name == setPlaybackSpeedMethodReference.name } setPlaybackSpeedMethodIndex = 0 // Add override playback speed method. @@ -264,12 +264,14 @@ val videoInformationPatch = bytecodePatch( // Handle new playback speed menu. playbackSpeedMenuSpeedChangedFingerprint.match( newVideoQualityChangedFingerprint.originalClassDef, - ).method.apply { - val index = indexOfFirstInstructionOrThrow(Opcode.IGET) + ).let { + it.method.apply { + val index = it.instructionMatches.first().index - speedSelectionInsertMethod = this - speedSelectionInsertIndex = index + 1 - speedSelectionValueRegister = getInstruction(index).registerA + speedSelectionInsertMethod = this + speedSelectionInsertIndex = index + 1 + speedSelectionValueRegister = getInstruction(index).registerA + } } videoSpeedChangedHook(EXTENSION_CLASS_DESCRIPTOR, "videoSpeedChanged") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt index d958285b4d..8f4e88a2d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt @@ -1,13 +1,13 @@ package app.revanced.patches.youtube.video.playerresponse import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags -import org.stringtemplate.v4.compiler.Bytecode.instructions /** * For targets 20.15 and later. */ -internal val playerParameterBuilderFingerprint = fingerprint { +internal val playerParameterBuilderFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters( @@ -25,15 +25,17 @@ internal val playerParameterBuilderFingerprint = fingerprint { "L", "Z", // Appears to indicate if the video id is being opened or is currently playing. "Z", - "Z" + "Z", + ) + instructions( + string("psps") ) - strings("psps") } /** * For targets 20.10 to 20.14. */ -internal val playerParameterBuilder2010Fingerprint = fingerprint { +internal val playerParameterBuilder2010Fingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters( @@ -54,13 +56,15 @@ internal val playerParameterBuilder2010Fingerprint = fingerprint { "Z", "Z" ) - strings("psps") + instructions( + string("psps") + ) } /** * For targets 20.02 to 20.09. */ -internal val playerParameterBuilder2002Fingerprint = fingerprint { +internal val playerParameterBuilder2002Fingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters( @@ -80,13 +84,15 @@ internal val playerParameterBuilder2002Fingerprint = fingerprint { "Z", "Z", ) - strings("psps") + instructions( + string("psps"), + ) } /** * For targets 19.25 to 19.50. */ -internal val playerParameterBuilder1925Fingerprint = fingerprint { +internal val playerParameterBuilder1925Fingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters( @@ -105,13 +111,15 @@ internal val playerParameterBuilder1925Fingerprint = fingerprint { "Z", "Z", ) - strings("psps") + instructions( + string("psps") + ) } /** - * For targets 19.24 and earlier. + * For targets 19.01 to 19.24. */ -internal val playerParameterBuilderLegacyFingerprint = fingerprint { +internal val playerParameterBuilderLegacyFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt index 55285a56e3..21fb6897c3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt @@ -8,9 +8,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter @@ -30,15 +29,15 @@ private val advancedVideoQualityMenuResourcePatch = resourcePatch { execute { // Used for the old type of the video quality menu. - videoQualityBottomSheetListFragmentTitle = resourceMappings[ + videoQualityBottomSheetListFragmentTitle = getResourceId( "layout", "video_quality_bottom_sheet_list_fragment_title", - ] + ) - videoQualityQuickMenuAdvancedMenuDescription = resourceMappings[ + videoQualityQuickMenuAdvancedMenuDescription = getResourceId( "string", "video_quality_quick_menu_advanced_menu_description", - ] + ) } } @@ -71,7 +70,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { videoQualityMenuViewInflateFingerprint.let { it.method.apply { - val checkCastIndex = it.patternMatch!!.endIndex + val checkCastIndex = it.instructionMatches.last().index val listViewRegister = getInstruction(checkCastIndex).registerA addInstruction( @@ -84,9 +83,9 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { // Force YT to add the 'advanced' quality menu for Shorts. videoQualityMenuOptionsFingerprint.let { - val patternMatch = it.patternMatch!! - val startIndex = patternMatch.startIndex - val insertIndex = patternMatch.endIndex + val patternMatch = it.instructionMatches + val startIndex = patternMatch.first().index + val insertIndex = patternMatch.last().index if (startIndex != 0) throw PatchException("Unexpected opcode start index: $startIndex") it.method.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt index 5ce6da9c11..d6b9f40c2e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt @@ -1,6 +1,7 @@ package app.revanced.patches.youtube.video.quality import app.revanced.patcher.fingerprint +import app.revanced.patcher.string import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -8,7 +9,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * Matches with the class found in [videoQualitySetterFingerprint]. */ -internal val setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint { +internal val setQualityByIndexMethodClassFieldReferenceFingerprint by fingerprint { returns("V") parameters("L") opcodes( @@ -18,12 +19,14 @@ internal val setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint ) } -internal val videoQualityItemOnClickParentFingerprint = fingerprint { +internal val videoQualityItemOnClickParentFingerprint by fingerprint { returns("V") - strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") + instructions( + string("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT"), + ) } -internal val videoQualitySetterFingerprint = fingerprint { +internal val videoQualitySetterFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("[L", "I", "Z") @@ -38,7 +41,7 @@ internal val videoQualitySetterFingerprint = fingerprint { } -internal val videoQualityMenuOptionsFingerprint = fingerprint { +internal val videoQualityMenuOptionsFingerprint by fingerprint { accessFlags(AccessFlags.STATIC) returns("[L") parameters("Landroid/content/Context", "L", "L") @@ -52,7 +55,7 @@ internal val videoQualityMenuOptionsFingerprint = fingerprint { literal { videoQualityQuickMenuAdvancedMenuDescription } } -internal val videoQualityMenuViewInflateFingerprint = fingerprint { +internal val videoQualityMenuViewInflateFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("L") parameters("L", "L", "L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 79e2fade40..7f6c953747 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -85,11 +85,9 @@ val rememberVideoQualityPatch = bytecodePatch { val setQualityByIndexMethodClassFieldReference = getSetQualityByIndexMethodClassFieldReference as FieldReference - val setQualityByIndexMethodClass = classes - .find { classDef -> classDef.type == setQualityByIndexMethodClassFieldReference.type }!! - // Get the name of the setQualityByIndex method. - val setQualityByIndexMethod = setQualityByIndexMethodClass.methods + val setQualityByIndexMethod = classBy(setQualityByIndexMethodClassFieldReference.type) + .methods .find { method -> method.parameterTypes.first() == "I" } ?: throw PatchException("Could not find setQualityByIndex method") @@ -128,7 +126,7 @@ val rememberVideoQualityPatch = bytecodePatch { // Remember video quality if not using old layout menu. newVideoQualityChangedFingerprint.method.apply { - val index = newVideoQualityChangedFingerprint.patternMatch!!.startIndex + val index = newVideoQualityChangedFingerprint.instructionMatches[3].index val qualityRegister = getInstruction(index).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt index 027be3a1bf..7e42a4d46d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt @@ -9,26 +9,24 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.InputType import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference -import app.revanced.patches.youtube.interaction.seekbar.disableFastForwardNoticeFingerprint +import app.revanced.patches.youtube.interaction.seekbar.customTapAndHoldFingerprint import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch -import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater +import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTreeHook import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup -import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstruction import app.revanced.util.indexOfFirstLiteralInstructionOrThrow -import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;" -private const val EXTENSION_CLASS_DESCRIPTOR = +internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;" internal val customPlaybackSpeedPatch = bytecodePatch( @@ -40,7 +38,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( addResourcesPatch, lithoFilterPatch, versionCheckPatch, - recyclerViewTreeHookPatch + recyclerViewTreeHookPatch, ) execute { @@ -56,7 +54,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( ) ) - if (is_19_25_or_greater) { + if (is_19_47_or_greater) { settingsMenuVideoSpeedGroup.add( TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL), ) @@ -89,11 +87,9 @@ internal val customPlaybackSpeedPatch = bytecodePatch( // region Custom tap and hold 2x speed. - if (is_19_25_or_greater) { - disableFastForwardNoticeFingerprint.method.apply { - val index = indexOfFirstInstructionOrThrow { - (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() - } + if (is_19_47_or_greater) { + customTapAndHoldFingerprint.method.apply { + val index = indexOfFirstLiteralInstructionOrThrow(2.0f) val register = getInstruction(index).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt index 120bb1df3c..3bcc2f462c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val speedLimiterFingerprint = fingerprint { +internal val speedLimiterFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("F") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/Fingerprints.kt index 3924588b42..5c73615f71 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/Fingerprints.kt @@ -1,8 +1,11 @@ package app.revanced.patches.youtube.video.speed.remember import app.revanced.patcher.fingerprint +import app.revanced.patcher.string -internal val initializePlaybackSpeedValuesFingerprint = fingerprint { +internal val initializePlaybackSpeedValuesFingerprint by fingerprint { parameters("[L", "I") - strings("menu_item_playback_speed") + instructions( + string("menu_item_playback_speed"), + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt index 6d4a3c6cb8..9c8fbbc23c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt @@ -1,55 +1,54 @@ package app.revanced.patches.youtube.video.videoid import app.revanced.patcher.fingerprint -import app.revanced.util.literal +import app.revanced.patcher.literal +import app.revanced.patcher.methodCall +import app.revanced.patcher.opcode import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val videoIdFingerprint = fingerprint { +internal val videoIdFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("L") - opcodes( - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, + instructions( + methodCall( + definingClass = "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;", + returnType = "Ljava/lang/String;" + ), + opcode(Opcode.MOVE_RESULT_OBJECT), ) - custom { method, _ -> - method.indexOfPlayerResponseModelString() >= 0 - } } -internal val videoIdBackgroundPlayFingerprint = fingerprint { +internal val videoIdBackgroundPlayFingerprint by fingerprint { accessFlags(AccessFlags.DECLARED_SYNCHRONIZED, AccessFlags.FINAL, AccessFlags.PUBLIC) returns("V") parameters("L") - opcodes( - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MONITOR_EXIT, - Opcode.RETURN_VOID, - Opcode.MONITOR_EXIT, - Opcode.RETURN_VOID + instructions( + methodCall( + definingClass = "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;", + returnType = "Ljava/lang/String;" + ), + opcode(Opcode.MOVE_RESULT_OBJECT), + opcode(Opcode.IPUT_OBJECT), + opcode(Opcode.MONITOR_EXIT), + opcode(Opcode.RETURN_VOID), + opcode(Opcode.MONITOR_EXIT), + opcode(Opcode.RETURN_VOID) ) // The target snippet of code is buried in a huge switch block and the target method // has been changed many times by YT which makes identifying it more difficult than usual. custom { method, classDef -> - // Access flags changed in 19.36 - AccessFlags.FINAL.isSet(method.accessFlags) && - AccessFlags.DECLARED_SYNCHRONIZED.isSet(method.accessFlags) && - classDef.methods.count() == 17 && - method.implementation != null && - method.indexOfPlayerResponseModelString() >= 0 + classDef.methods.count() == 17 && + method.implementation != null } - } -internal val videoIdParentFingerprint = fingerprint { +internal val videoIdParentFingerprint by fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("[L") parameters("L") - literal { 524288L } + instructions( + literal(524288L) + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index 6d69381cd3..7ffdb3b2e0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -9,11 +9,7 @@ import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.video.playerresponse.Hook import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * Hooks the new video id when the video changes. @@ -96,24 +92,22 @@ val videoIdPatch = bytecodePatch( ) execute { - videoIdFingerprint.match(videoIdParentFingerprint.originalClassDef).method.apply { - videoIdMethod = this - val index = indexOfPlayerResponseModelString() - videoIdRegister = getInstruction(index + 1).registerA - videoIdInsertIndex = index + 2 + videoIdFingerprint.match(videoIdParentFingerprint.originalClassDef).let { + it.method.apply { + videoIdMethod = this + val index = it.instructionMatches.first().index + videoIdRegister = getInstruction(index + 1).registerA + videoIdInsertIndex = index + 2 + } } - videoIdBackgroundPlayFingerprint.method.apply { - backgroundPlaybackMethod = this - val index = indexOfPlayerResponseModelString() - backgroundPlaybackVideoIdRegister = getInstruction(index + 1).registerA - backgroundPlaybackInsertIndex = index + 2 + videoIdBackgroundPlayFingerprint.let { + it.method.apply { + backgroundPlaybackMethod = this + val index = it.instructionMatches.first().index + backgroundPlaybackVideoIdRegister = getInstruction(index + 1).registerA + backgroundPlaybackInsertIndex = index + 2 + } } } -} - -internal fun Method.indexOfPlayerResponseModelString() = indexOfFirstInstruction { - val reference = getReference() - reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" && - reference.returnType == "Ljava/lang/String;" -} +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt deleted file mode 100644 index 537a2b68c4..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.video.videoqualitymenu - -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.youtube.video.quality.videoQualityPatch - -@Suppress("unused") -@Deprecated("Use 'Video Quality' instead.") -val restoreOldVideoQualityMenuPatch = bytecodePatch { - dependsOn(videoQualityPatch) -} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/Fingerprints.kt deleted file mode 100644 index af38f28f4d..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/Fingerprints.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.yuka.misc.unlockpremium - -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.AccessFlags -import app.revanced.patcher.fingerprint - -internal val isPremiumFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Z") - opcodes( - Opcode.IGET_BOOLEAN, - Opcode.RETURN, - ) -} - -internal val yukaUserConstructorFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - returns("V") - strings("premiumProvider") -} diff --git a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt deleted file mode 100644 index c4cedd0927..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.yuka.misc.unlockpremium - -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.bytecodePatch - -@Deprecated("This patch no longer works and will be removed in the future.") -@Suppress("unused") -val unlockPremiumPatch = bytecodePatch { - - compatibleWith("io.yuka.android"("4.29")) - - execute { - isPremiumFingerprint.match( - yukaUserConstructorFingerprint.originalClassDef, - ).method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """, - ) - } -} diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 017a998626..3a2cb20737 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -14,9 +14,8 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableField import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.shared.misc.mapping.get +import app.revanced.patches.shared.misc.mapping.getResourceId import app.revanced.patches.shared.misc.mapping.resourceMappingPatch -import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.util.InstructionUtils.Companion.branchOpcodes import app.revanced.util.InstructionUtils.Companion.returnOpcodes import app.revanced.util.InstructionUtils.Companion.writeOpcodes @@ -94,7 +93,8 @@ fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude: Int): In return bestFreeRegisterFound } // This method is simple and does not follow branching. - throw IllegalArgumentException("Encountered a branch statement before a free register could be found") + throw IllegalArgumentException("Encountered a branch statement before " + + "a free register could be found from startIndex: $startIndex") } if (instruction.isReturnInstruction) { @@ -282,7 +282,7 @@ fun MutableMethod.addInstructionsAtControlFlowLabel( * @see [indexOfFirstResourceIdOrThrow], [indexOfFirstLiteralInstructionReversed] */ fun Method.indexOfFirstResourceId(resourceName: String): Int { - val resourceId = resourceMappings["id", resourceName] + val resourceId = getResourceId("id", resourceName) return indexOfFirstLiteralInstruction(resourceId) } @@ -467,7 +467,7 @@ fun BytecodePatchContext.traverseClassHierarchy(targetClass: MutableClass, callb targetClass.superclass ?: return - classBy { targetClass.superclass == it.type }?.mutableClass?.let { + mutableClassByOrNull(targetClass.superclass!!)?.let { traverseClassHierarchy(it, callback) } } @@ -679,8 +679,12 @@ fun Method.findInstructionIndicesReversedOrThrow(opcode: Opcode): List { * Suitable for calls to extension code to override boolean and integer values. */ internal fun MutableMethod.insertLiteralOverride(literal: Long, extensionMethodDescriptor: String) { - // TODO: make this work with objects and wide values. val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal) + insertLiteralOverride(literalIndex, extensionMethodDescriptor) +} + +internal fun MutableMethod.insertLiteralOverride(literalIndex: Int, extensionMethodDescriptor: String) { + // TODO: make this work with objects and wide primitive values. val index = indexOfFirstInstructionOrThrow(literalIndex, MOVE_RESULT) val register = getInstruction(index).registerA @@ -704,6 +708,13 @@ internal fun MutableMethod.insertLiteralOverride(literal: Long, extensionMethodD */ internal fun MutableMethod.insertLiteralOverride(literal: Long, override: Boolean) { val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal) + return insertLiteralOverride(literalIndex, override) +} + +/** + * Constant value override of the first MOVE_RESULT after the index parameter. + */ +internal fun MutableMethod.insertLiteralOverride(literalIndex: Int, override: Boolean) { val index = indexOfFirstInstructionOrThrow(literalIndex, MOVE_RESULT) val register = getInstruction(index).registerA val overrideValue = if (override) "0x1" else "0x0" @@ -727,7 +738,7 @@ fun BytecodePatchContext.forEachLiteralValueInstruction( if (instruction.opcode == CONST && (instruction as WideLiteralInstruction).wideLiteral == literal ) { - val mutableMethod = proxy(classDef).mutableClass.findMutableMethodOf(method) + val mutableMethod = mutableClassBy(classDef).findMutableMethodOf(method) block.invoke(mutableMethod, index) } } @@ -1037,10 +1048,7 @@ internal fun BytecodePatchContext.addStaticFieldToExtension( objectClass: String, smaliInstructions: String ) { - val classDef = classes.find { classDef -> classDef.type == className } - ?: throw PatchException("No matching methods found in: $className") - val mutableClass = proxy(classDef).mutableClass - + val mutableClass = mutableClassBy(className) val objectCall = "$mutableClass->$fieldName:$objectClass" mutableClass.apply { @@ -1072,7 +1080,7 @@ internal fun BytecodePatchContext.addStaticFieldToExtension( * * @param literalSupplier The supplier for the literal value to check for. */ -// TODO: add a way for subclasses to also use their own custom fingerprint. +@Deprecated("Instead use instruction filters and `literal()`") fun FingerprintBuilder.literal(literalSupplier: () -> Long) { custom { method, _ -> method.containsLiteralInstruction(literalSupplier()) diff --git a/patches/src/main/resources/addresources/values/arrays.xml b/patches/src/main/resources/addresources/values/arrays.xml index 6e5c17deaa..3fb26d736b 100644 --- a/patches/src/main/resources/addresources/values/arrays.xml +++ b/patches/src/main/resources/addresources/values/arrays.xml @@ -331,15 +331,6 @@ - - @string/revanced_shorts_player_type_shorts - @string/revanced_shorts_player_type_regular_player - - - - SHORTS_PLAYER - REGULAR_PLAYER - @string/revanced_shorts_player_type_shorts @string/revanced_shorts_player_type_regular_player diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 07daa21c5d..6ccefc70f8 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -660,6 +660,9 @@ If changing this setting does not take effect, try switching to Incognito mode." Hide navigation button labels Labels are hidden Labels are shown + Enable navigation bar animations + Navigation transitions are animated + Navigation transitions are not animated Disable translucent status bar Status bar is opaque Status bar is opaque or translucent