Skip to content

fix(YouTube): Simplify litho filtering patch #4910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ private static void findAsciiStrings(StringBuilder builder, byte[] buffer) {
* the buffer is saved to a ThreadLocal so each calling thread does not interfere with other threads.
*/
private static final ThreadLocal<ByteBuffer> bufferThreadLocal = new ThreadLocal<>();
/**
* Results of calling {@link #filter(String, StringBuilder)}.
*/
private static final ThreadLocal<Boolean> filterResult = new ThreadLocal<>();

static {
for (Filter filter : filters) {
Expand Down Expand Up @@ -140,11 +144,22 @@ public static void setProtoBuffer(@Nullable ByteBuffer protobufBuffer) {
}
}

/**
* 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.
*/
@SuppressWarnings("unused")
public static boolean filter(@Nullable String lithoIdentifier, @NonNull StringBuilder pathBuilder) {
public static void filter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) {
filterResult.set(handleFiltering(lithoIdentifier, pathBuilder));
}

private static boolean handleFiltering(@Nullable String lithoIdentifier, StringBuilder pathBuilder) {
try {
if (pathBuilder.length() == 0) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,6 @@ import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

internal val conversionContextFingerprint = fingerprint {
returns("Ljava/lang/String;")
parameters()
strings(
", widthConstraint=",
", heightConstraint=",
", templateLoggerFactory=",
", rootDisposableContainer=",
"ConversionContext{containerInternal=",
)
}

internal val dislikeFingerprint = fingerprint {
returns("V")
strings("like/dislike")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.addSettingPreference
import app.revanced.patches.youtube.misc.settings.newIntent
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.conversionContextFingerprint
import app.revanced.patches.youtube.shared.rollingNumberTextViewAnimationUpdateFingerprint
import app.revanced.patches.youtube.video.videoid.hookPlayerResponseVideoId
import app.revanced.patches.youtube.video.videoid.hookVideoId
Expand Down Expand Up @@ -117,7 +118,7 @@ val returnYouTubeDislikePatch = bytecodePatch(
} ?: throw PatchException("Could not find conversion context field")

textComponentLookupFingerprint.match(textComponentConstructorFingerprint.originalClassDef)
textComponentLookupFingerprint.method.apply {
.method.apply {
// Find the instruction for creating the text data object.
val textDataClassType = textComponentDataFingerprint.originalClassDef.type

Expand Down Expand Up @@ -160,12 +161,12 @@ val returnYouTubeDislikePatch = bytecodePatch(
addInstructionsAtControlFlowLabel(
insertIndex,
"""
# Copy conversion context
move-object/from16 v$tempRegister, p0
iget-object v$tempRegister, v$tempRegister, $conversionContextField
invoke-static { v$tempRegister, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$charSequenceRegister
""",
# Copy conversion context
move-object/from16 v$tempRegister, p0
iget-object v$tempRegister, v$tempRegister, $conversionContextField
invoke-static { v$tempRegister, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$charSequenceRegister
"""
)
}

Expand Down Expand Up @@ -201,11 +202,9 @@ val returnYouTubeDislikePatch = bytecodePatch(
val charSequenceFieldReference =
getInstruction<ReferenceInstruction>(dislikesIndex).reference

val registerCount = implementation!!.registerCount
val conversionContextRegister = implementation!!.registerCount - parameters.size + 1

// This register is being overwritten, so it is free to use.
val freeRegister = registerCount - 1
val conversionContextRegister = registerCount - parameters.size + 1
val freeRegister = findFreeRegister(insertIndex, charSequenceInstanceRegister, conversionContextRegister)

addInstructions(
insertIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

/**
* In 19.17 and earlier, this resolves to the same method as [readComponentIdentifierFingerprint].
* In 19.18+ this resolves to a different method.
*/
internal val componentContextParserFingerprint = fingerprint {
strings(
"TreeNode result must be set.",
Expand All @@ -21,7 +17,7 @@ internal val lithoFilterFingerprint = fingerprint {
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
returns("V")
custom { _, classDef ->
classDef.endsWith("LithoFilterPatch;")
classDef.endsWith("/LithoFilterPatch;")
}
}

Expand All @@ -37,16 +33,10 @@ internal val protobufBufferReferenceFingerprint = fingerprint {
)
}

/**
* In 19.17 and earlier, this resolves to the same method as [componentContextParserFingerprint].
* In 19.18+ this resolves to a different method.
*/
internal val readComponentIdentifierFingerprint = fingerprint {
strings("Number of bits must be positive")
}

internal val elementConfigFingerprint = fingerprint {
strings(" enableDroppedFrameLogging", " elementDepthInTree")
internal val converterTreeDebugFingerprint = fingerprint {
returns("L")
opcodes(Opcode.IGET_OBJECT)
strings("Element tree missing id in debug mode.")
}

internal val emptyComponentFingerprint = fingerprint {
Expand Down
Loading
Loading