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 df965b8a9b
commit e30f593af0
6 changed files with 56 additions and 6 deletions

View File

@@ -0,0 +1,8 @@
package com.spotify.useraccount.v1;
/**
* Used for target 8.6.98.900. Class is still present in newer app targets.
*/
public class AccountAttribute {
public Object value_;
}

View File

@@ -92,7 +92,7 @@ fun sharedExtensionPatch(
} }
class ExtensionHook internal constructor( class ExtensionHook internal constructor(
private val fingerprint: Fingerprint, internal val fingerprint: Fingerprint,
private val insertIndexResolver: ((Method) -> Int), private val insertIndexResolver: ((Method) -> Int),
private val contextRegisterResolver: (Method) -> String, 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.fingerprint
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod 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.patches.spotify.misc.extension.sharedExtensionPatch
import app.revanced.util.* import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
@@ -21,6 +22,12 @@ internal val customThemeByteCodePatch = bytecodePatch {
val backgroundColorSecondary by spotifyBackgroundColorSecondary val backgroundColorSecondary by spotifyBackgroundColorSecondary
execute { 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) { fun MutableMethod.addColorChangeInstructions(literal: Long, colorString: String) {
val index = indexOfFirstLiteralInstructionOrThrow(literal) val index = indexOfFirstLiteralInstructionOrThrow(literal)
val register = getInstruction<OneRegisterInstruction>(index).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA

View File

@@ -1,16 +1,29 @@
package app.revanced.patches.spotify.misc package app.revanced.patches.spotify.misc
import app.revanced.patcher.fingerprint 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.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal val accountAttributeFingerprint = fingerprint { 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 { internal val productStateProtoFingerprint = fingerprint {
returns("Ljava/util/Map;") 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 { internal val buildQueryParametersFingerprint = fingerprint {

View File

@@ -1,5 +1,20 @@
package app.revanced.patches.spotify.misc.extension package app.revanced.patches.spotify.misc.extension
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch 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 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 { internal val spotifyMainActivityOnCreate = extensionHook {
custom { method, classDef -> custom { method, classDef ->
classDef.type == "Lcom/spotify/music/SpotifyMainActivity;" && method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY
method.name == "onCreate" || classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY)
} }
} }