feat(Spotify): Add limited support for version 8.6.98.900 (last version that supports Kenwood and Pioneer car stereos) (#4750)

This commit is contained in:
LisoUseInAIKyrios
2025-04-11 21:30:47 +02:00
committed by GitHub
parent b91285ec20
commit a3fde874af
8 changed files with 92 additions and 11 deletions

View File

@ -92,7 +92,7 @@ fun sharedExtensionPatch(
}
class ExtensionHook internal constructor(
private val fingerprint: Fingerprint,
internal val fingerprint: Fingerprint,
private val insertIndexResolver: ((Method) -> Int),
private val contextRegisterResolver: (Method) -> String,
) {

View File

@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
@ -21,6 +22,12 @@ internal val customThemeByteCodePatch = bytecodePatch {
val backgroundColorSecondary by spotifyBackgroundColorSecondary
execute {
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
// Bytecode changes are not needed for legacy app target.
// Player background color is changed with existing resource patch.
return@execute
}
fun MutableMethod.addColorChangeInstructions(literal: Long, colorString: String) {
val index = indexOfFirstLiteralInstructionOrThrow(literal)
val register = getInstruction<OneRegisterInstruction>(index).registerA

View File

@ -1,16 +1,29 @@
package app.revanced.patches.spotify.misc
import app.revanced.patcher.fingerprint
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal val accountAttributeFingerprint = fingerprint {
custom { _, classDef -> classDef.endsWith("internal/AccountAttribute;") }
custom { _, classDef ->
classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) {
"Lcom/spotify/useraccount/v1/AccountAttribute;"
} else {
"Lcom/spotify/remoteconfig/internal/AccountAttribute;"
}
}
}
internal val productStateProtoFingerprint = fingerprint {
returns("Ljava/util/Map;")
custom { _, classDef -> classDef.endsWith("ProductStateProto;") }
custom { _, classDef ->
classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) {
"Lcom/spotify/ucs/proto/v0/UcsResponseWrapper${'$'}AccountAttributesResponse;"
} else {
"Lcom/spotify/remoteconfig/internal/ProductStateProto;"
}
}
}
internal val buildQueryParametersFingerprint = fingerprint {

View File

@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
@ -14,6 +15,7 @@ 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 java.util.logging.Logger
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/misc/UnlockPremiumPatch;"
@ -53,6 +55,12 @@ val unlockPremiumPatch = bytecodePatch(
method.replaceInstruction(addQueryParameterConditionIndex, "nop")
}
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
return@execute Logger.getLogger(this::class.java.name).info(
"Patching a legacy Spotify version. Patch functionality may be limited."
)
}
// Disable the "Spotify Premium" upsell experiment in context menus.
with(contextMenuExperimentsFingerprint) {
val moveIsEnabledIndex = method.indexOfFirstInstructionOrThrow(

View File

@ -1,5 +1,20 @@
package app.revanced.patches.spotify.misc.extension
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch("spotify", spotifyMainActivityOnCreate)
/**
* If patching a legacy 8.x target. This may also be set if patching slightly older/newer app targets,
* but the only legacy target of interest is 8.6.98.900 as it's the last version that
* supports Spotify integration on Kenwood/Pioneer car stereos.
*/
internal var IS_SPOTIFY_LEGACY_APP_TARGET = false
val sharedExtensionPatch = bytecodePatch {
dependsOn(sharedExtensionPatch("spotify", spotifyMainActivityOnCreate))
execute {
IS_SPOTIFY_LEGACY_APP_TARGET = spotifyMainActivityOnCreate.fingerprint
.originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY
}
}

View File

@ -2,9 +2,16 @@ package app.revanced.patches.spotify.misc.extension
import app.revanced.patches.shared.misc.extension.extensionHook
private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivity;"
/**
* Main activity of target 8.6.98.900.
*/
internal const val SPOTIFY_MAIN_ACTIVITY_LEGACY = "Lcom/spotify/music/MainActivity;"
internal val spotifyMainActivityOnCreate = extensionHook {
custom { method, classDef ->
classDef.type == "Lcom/spotify/music/SpotifyMainActivity;" &&
method.name == "onCreate"
method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY
|| classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY)
}
}