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 c6fe5fcec..28098f44e 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 @@ -2,8 +2,12 @@ package app.revanced.patches.spotify.misc import app.revanced.patcher.fingerprint import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET +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.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.TypeReference internal val accountAttributeFingerprint = fingerprint { custom { _, classDef -> @@ -15,7 +19,7 @@ internal val accountAttributeFingerprint = fingerprint { } } -internal val productStateProtoFingerprint = fingerprint { +internal val productStateProtoGetMapFingerprint = fingerprint { returns("Ljava/util/Map;") custom { _, classDef -> classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) { @@ -56,16 +60,41 @@ internal val readPlayerOptionOverridesFingerprint = fingerprint { } } -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;") } +internal val protobufListRemoveFingerprint = fingerprint { + custom { method, _ -> method.name == "remove" } } + +internal val homeSectionFingerprint = fingerprint { + custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") } +} + +internal val homeStructureGetSectionsFingerprint = fingerprint { + custom { method, classDef -> + classDef.endsWith("homeapi/proto/HomeStructure;") && method.indexOfFirstInstruction { + opcode == Opcode.IGET_OBJECT && getReference()?.name == "sections_" + } >= 0 + } +} + +internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = fingerprint { + accessFlags(AccessFlags.PUBLIC) + returns("Ljava/lang/Object;") + parameters("Ljava/lang/Object;") + custom { method, _ -> method.name == "apply" && method.indexOfFirstInstruction { + opcode == Opcode.NEW_INSTANCE && getReference()?.type?.endsWith(className) == true + } >= 0 + } +} + +internal const val PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME = "FetchMessageRequest;" +internal val pendragonJsonFetchMessageRequestFingerprint = + reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME) + +internal const val PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME = "FetchMessageListRequest;" +internal val pendragonProtoFetchMessageListRequestFingerprint = + reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME) 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 2836a4872..58606777d 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 @@ -60,4 +60,4 @@ val spoofPackageInfoPatch = bytecodePatch( // endregion } } -} \ No newline at end of file +} 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 14149ac7a..1afbcde45 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 @@ -14,4 +14,4 @@ internal val mainActivityOnCreateFingerprint = fingerprint { method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY || classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY) } -} \ No newline at end of file +} diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 7005ed47a..1e711271c 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -18,6 +18,7 @@ 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 +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode.* import com.android.tools.smali.dexlib2.iface.Method @@ -169,6 +170,15 @@ internal val Instruction.isBranchInstruction: Boolean internal val Instruction.isReturnInstruction: Boolean get() = this.opcode in returnOpcodes +/** + * Adds public [AccessFlags] and removes private and protected flags (if present). + */ +internal fun Int.toPublicAccessFlags() : Int { + return this.or(AccessFlags.PUBLIC.value) + .and(AccessFlags.PROTECTED.value.inv()) + .and(AccessFlags.PRIVATE.value.inv()) +} + /** * Find the [MutableMethod] from a given [Method] in a [MutableClass]. *