fix(Spotify): Remove ads sections from home (#4722)

Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
This commit is contained in:
Nuckyz
2025-04-04 09:32:40 -03:00
committed by GitHub
parent 36772b8b2e
commit 628d18489c
3 changed files with 42 additions and 13 deletions

View File

@@ -0,0 +1,7 @@
package com.spotify.home.evopage.homeapi.proto;
public final class Section {
public static final int VIDEO_BRAND_AD_FIELD_NUMBER = 20;
public static final int IMAGE_BRAND_AD_FIELD_NUMBER = 21;
public int featureTypeCase_;
}

View File

@@ -1,16 +1,16 @@
package app.revanced.patches.spotify.misc package app.revanced.patches.spotify.misc
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val accountAttributeFingerprint = fingerprint { internal val accountAttributeFingerprint = fingerprint {
custom { _, c -> c.endsWith("internal/AccountAttribute;") } custom { _, classDef -> classDef.endsWith("internal/AccountAttribute;") }
} }
internal val productStateProtoFingerprint = fingerprint { internal val productStateProtoFingerprint = fingerprint {
returns("Ljava/util/Map;") returns("Ljava/util/Map;")
custom { _, classDef -> custom { _, classDef -> classDef.endsWith("ProductStateProto;") }
classDef.endsWith("ProductStateProto;")
}
} }
internal val buildQueryParametersFingerprint = fingerprint { internal val buildQueryParametersFingerprint = fingerprint {
@@ -21,3 +21,17 @@ internal val contextMenuExperimentsFingerprint = fingerprint {
parameters("L") parameters("L")
strings("remove_ads_upsell_enabled") strings("remove_ads_upsell_enabled")
} }
internal val homeSectionFingerprint = fingerprint {
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
}
internal val protobufListsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
custom { method, _ -> method.name == "emptyProtobufList" }
}
internal val homeStructureFingerprint = fingerprint {
opcodes(Opcode.IGET_OBJECT, Opcode.RETURN_OBJECT)
custom { _, classDef -> classDef.endsWith("homeapi/proto/HomeStructure;") }
}

View File

@@ -53,7 +53,15 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
// All registers used by an instruction. // All registers used by an instruction.
fun Instruction.getRegistersUsed() = when (this) { fun Instruction.getRegistersUsed() = when (this) {
is FiveRegisterInstruction -> listOf(registerC, registerD, registerE, registerF, registerG) is FiveRegisterInstruction -> {
when (registerCount) {
1 -> listOf(registerC)
2 -> listOf(registerC, registerD)
3 -> listOf(registerC, registerD, registerE)
4 -> listOf(registerC, registerD, registerE, registerF)
else -> listOf(registerC, registerD, registerE, registerF, registerG)
}
}
is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC) is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC)
is TwoRegisterInstruction -> listOf(registerA, registerB) is TwoRegisterInstruction -> listOf(registerA, registerB)
is OneRegisterInstruction -> listOf(registerA) is OneRegisterInstruction -> listOf(registerA)
@@ -62,15 +70,15 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
} }
// Register that is written to by an instruction. // Register that is written to by an instruction.
fun Instruction.getRegisterWritten() = when (this) { fun Instruction.getWriteRegister() : Int {
is ThreeRegisterInstruction -> registerA // Two and three register instructions extend OneRegisterInstruction.
is TwoRegisterInstruction -> registerA if (this is OneRegisterInstruction) return registerA
is OneRegisterInstruction -> registerA throw IllegalStateException("Not a write instruction: $this")
else -> throw IllegalStateException("Not a write instruction: $this")
} }
val writeOpcodes = EnumSet.of( val writeOpcodes = EnumSet.of(
ARRAY_LENGTH, ARRAY_LENGTH,
INSTANCE_OF,
NEW_INSTANCE, NEW_ARRAY, NEW_INSTANCE, NEW_ARRAY,
MOVE, MOVE_FROM16, MOVE_16, MOVE_WIDE, MOVE_WIDE_FROM16, MOVE_WIDE_16, MOVE_OBJECT, MOVE, MOVE_FROM16, MOVE_16, MOVE_WIDE, MOVE_WIDE_FROM16, MOVE_WIDE_16, MOVE_OBJECT,
MOVE_OBJECT_FROM16, MOVE_OBJECT_16, MOVE_RESULT, MOVE_RESULT_WIDE, MOVE_RESULT_OBJECT, MOVE_EXCEPTION, MOVE_OBJECT_FROM16, MOVE_OBJECT_16, MOVE_RESULT, MOVE_RESULT_WIDE, MOVE_RESULT_OBJECT, MOVE_EXCEPTION,
@@ -140,7 +148,7 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
return freeRegister return freeRegister
} }
if (bestFreeRegisterFound != null) { if (bestFreeRegisterFound != null) {
return bestFreeRegisterFound; return bestFreeRegisterFound
} }
// Somehow every method register was read from before any register was wrote to. // Somehow every method register was read from before any register was wrote to.
@@ -151,14 +159,14 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
if (instruction.opcode in branchOpcodes) { if (instruction.opcode in branchOpcodes) {
if (bestFreeRegisterFound != null) { if (bestFreeRegisterFound != null) {
return bestFreeRegisterFound; return bestFreeRegisterFound
} }
// This method is simple and does not follow branching. // 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")
} }
if (instruction.opcode in writeOpcodes) { if (instruction.opcode in writeOpcodes) {
val writeRegister = instruction.getRegisterWritten() val writeRegister = instruction.getWriteRegister()
if (writeRegister !in usedRegisters) { if (writeRegister !in usedRegisters) {
// Verify the register is only used for write and not also as a parameter. // Verify the register is only used for write and not also as a parameter.