Skip to content

Commit 9d31238

Browse files
authored
feat(Spotify): Remove support for old versions (#5404)
1 parent b1439da commit 9d31238

File tree

13 files changed

+36
-182
lines changed

13 files changed

+36
-182
lines changed

extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import app.revanced.extension.spotify.shared.ComponentFilters.ComponentFilter;
66
import app.revanced.extension.spotify.shared.ComponentFilters.ResourceIdComponentFilter;
77
import app.revanced.extension.spotify.shared.ComponentFilters.StringComponentFilter;
8+
import com.spotify.remoteconfig.internal.AccountAttribute;
89

910
import java.util.*;
1011

@@ -14,25 +15,6 @@
1415
@SuppressWarnings("unused")
1516
public final class UnlockPremiumPatch {
1617

17-
private static final String SPOTIFY_MAIN_ACTIVITY_LEGACY = "com.spotify.music.MainActivity";
18-
19-
/**
20-
* If the app target is 8.6.98.900.
21-
*/
22-
private static final boolean IS_SPOTIFY_LEGACY_APP_TARGET;
23-
24-
static {
25-
boolean isLegacy;
26-
try {
27-
Class.forName(SPOTIFY_MAIN_ACTIVITY_LEGACY);
28-
isLegacy = true;
29-
} catch (ClassNotFoundException ex) {
30-
isLegacy = false;
31-
}
32-
33-
IS_SPOTIFY_LEGACY_APP_TARGET = isLegacy;
34-
}
35-
3618
private static class OverrideAttribute {
3719
/**
3820
* Account attribute key.
@@ -66,7 +48,7 @@ private static class OverrideAttribute {
6648
new OverrideAttribute("ads", FALSE),
6749
// Works along on-demand, allows playing any song without restriction.
6850
new OverrideAttribute("player-license", "premium"),
69-
new OverrideAttribute("player-license-v2", "premium", !IS_SPOTIFY_LEGACY_APP_TARGET),
51+
new OverrideAttribute("player-license-v2", "premium"),
7052
// Disables shuffle being initially enabled when first playing a playlist.
7153
new OverrideAttribute("shuffle", FALSE),
7254
// Allows playing any song on-demand, without a shuffled order.
@@ -75,7 +57,7 @@ private static class OverrideAttribute {
7557
new OverrideAttribute("streaming", TRUE),
7658
// Allows adding songs to queue and removes the smart shuffle mode restriction,
7759
// allowing to pick any of the other modes. Flag is not present in legacy app target.
78-
new OverrideAttribute("pick-and-shuffle", FALSE, !IS_SPOTIFY_LEGACY_APP_TARGET),
60+
new OverrideAttribute("pick-and-shuffle", FALSE),
7961
// Disables shuffle-mode streaming-rule, which forces songs to be played shuffled
8062
// and breaks the player when other patches are applied.
8163
new OverrideAttribute("streaming-rules", ""),
@@ -131,10 +113,10 @@ private static class OverrideAttribute {
131113
/**
132114
* Injection point. Override account attributes.
133115
*/
134-
public static void overrideAttributes(Map<String, /*AccountAttribute*/ Object> attributes) {
116+
public static void overrideAttributes(Map<String, AccountAttribute> attributes) {
135117
try {
136118
for (OverrideAttribute override : PREMIUM_OVERRIDES) {
137-
Object attribute = attributes.get(override.key);
119+
AccountAttribute attribute = attributes.get(override.key);
138120

139121
if (attribute == null) {
140122
if (override.isExpected) {
@@ -145,11 +127,7 @@ public static void overrideAttributes(Map<String, /*AccountAttribute*/ Object> a
145127

146128
Object overrideValue = override.overrideValue;
147129
Object originalValue;
148-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
149-
originalValue = ((com.spotify.useraccount.v1.AccountAttribute) attribute).value_;
150-
} else {
151-
originalValue = ((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_;
152-
}
130+
originalValue = attribute.value_;
153131

154132
if (overrideValue.equals(originalValue)) {
155133
continue;
@@ -158,11 +136,7 @@ public static void overrideAttributes(Map<String, /*AccountAttribute*/ Object> a
158136
Logger.printInfo(() -> "Overriding account attribute " + override.key +
159137
" from " + originalValue + " to " + overrideValue);
160138

161-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
162-
((com.spotify.useraccount.v1.AccountAttribute) attribute).value_ = overrideValue;
163-
} else {
164-
((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_ = overrideValue;
165-
}
139+
attribute.value_ = overrideValue;
166140
}
167141
} catch (Exception ex) {
168142
Logger.printException(() -> "overrideAttributes failure", ex);

extensions/spotify/stub/src/main/java/com/spotify/useraccount/v1/AccountAttribute.java

Lines changed: 0 additions & 8 deletions
This file was deleted.

patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
66
import app.revanced.patcher.patch.bytecodePatch
77
import app.revanced.patcher.util.smali.ExternalLabel
88
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
9-
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
109
import app.revanced.util.getReference
1110
import app.revanced.util.indexOfFirstInstructionOrThrow
1211
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
1312
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
14-
import java.util.logging.Logger
1513

1614
private const val EXTENSION_CLASS_DESCRIPTOR =
1715
"Lapp/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch;"
@@ -26,13 +24,6 @@ val hideCreateButtonPatch = bytecodePatch(
2624
dependsOn(sharedExtensionPatch)
2725

2826
execute {
29-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
30-
Logger.getLogger(this::class.java.name).warning(
31-
"Create button does not exist in legacy app target. No changes applied."
32-
)
33-
return@execute
34-
}
35-
3627
val oldNavigationBarAddItemMethod = oldNavigationBarAddItemFingerprint.originalMethodOrNull
3728
// Only throw the fingerprint error when oldNavigationBarAddItemMethod does not exist.
3829
val navigationBarItemSetClassDef = if (oldNavigationBarAddItemMethod == null) {

patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import app.revanced.patcher.patch.bytecodePatch
77
import app.revanced.patcher.patch.resourcePatch
88
import app.revanced.patcher.patch.stringOption
99
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
10-
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
11-
import app.revanced.util.*
10+
import app.revanced.util.getReference
11+
import app.revanced.util.indexOfFirstInstructionOrThrow
1212
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
1313
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
1414
import org.w3c.dom.Element
@@ -19,12 +19,6 @@ private val customThemeBytecodePatch = bytecodePatch {
1919
dependsOn(sharedExtensionPatch)
2020

2121
execute {
22-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
23-
// Bytecode changes are not needed for legacy app target.
24-
// Player background color is changed with existing resource patch.
25-
return@execute
26-
}
27-
2822
val colorSpaceUtilsClassDef = colorSpaceUtilsClassFingerprint.originalClassDef
2923

3024
// Hook a util method that converts ARGB to RGBA in the sRGB color space to replace hardcoded accent colors.

patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
package app.revanced.patches.spotify.lite.ondemand
22

3-
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
43
import app.revanced.patcher.patch.bytecodePatch
54

65
@Deprecated("Patch no longer works and will be deleted soon")
76
@Suppress("unused")
87
val onDemandPatch = bytecodePatch(
98
description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.",
10-
) {
11-
compatibleWith("com.spotify.lite")
12-
13-
execute {
14-
// Spoof a premium account
15-
16-
onDemandFingerprint.method.addInstruction(
17-
onDemandFingerprint.patternMatch!!.endIndex - 1,
18-
"const/4 v0, 0x2",
19-
)
20-
}
21-
}
9+
)

patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package app.revanced.patches.spotify.misc
22

33
import app.revanced.patcher.fingerprint
44
import app.revanced.patcher.patch.BytecodePatchContext
5-
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
65
import app.revanced.util.getReference
76
import app.revanced.util.indexOfFirstInstruction
87
import com.android.tools.smali.dexlib2.AccessFlags
@@ -13,25 +12,13 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference
1312

1413
context(BytecodePatchContext)
1514
internal val accountAttributeFingerprint get() = fingerprint {
16-
custom { _, classDef ->
17-
classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) {
18-
"Lcom/spotify/useraccount/v1/AccountAttribute;"
19-
} else {
20-
"Lcom/spotify/remoteconfig/internal/AccountAttribute;"
21-
}
22-
}
15+
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/AccountAttribute;" }
2316
}
2417

2518
context(BytecodePatchContext)
2619
internal val productStateProtoGetMapFingerprint get() = fingerprint {
2720
returns("Ljava/util/Map;")
28-
custom { _, classDef ->
29-
classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) {
30-
"Lcom/spotify/ucs/proto/v0/UcsResponseWrapper${'$'}AccountAttributesResponse;"
31-
} else {
32-
"Lcom/spotify/remoteconfig/internal/ProductStateProto;"
33-
}
34-
}
21+
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/ProductStateProto;" }
3522
}
3623

3724
internal val buildQueryParametersFingerprint = fingerprint {
@@ -90,14 +77,14 @@ internal val contextFromJsonFingerprint = fingerprint {
9077
)
9178
custom { method, classDef ->
9279
method.name == "fromJson" &&
93-
classDef.endsWith("voiceassistants/playermodels/ContextJsonAdapter;")
80+
classDef.type.endsWith("voiceassistants/playermodels/ContextJsonAdapter;")
9481
}
9582
}
9683

9784
internal val readPlayerOptionOverridesFingerprint = fingerprint {
9885
custom { method, classDef ->
9986
method.name == "readPlayerOptionOverrides" &&
100-
classDef.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;")
87+
classDef.type.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;")
10188
}
10289
}
10390

@@ -119,21 +106,21 @@ internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint {
119106

120107
internal fun structureGetSectionsFingerprint(className: String) = fingerprint {
121108
custom { method, classDef ->
122-
classDef.endsWith(className) && method.indexOfFirstInstruction {
109+
classDef.type.endsWith(className) && method.indexOfFirstInstruction {
123110
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.name == "sections_"
124111
} >= 0
125112
}
126113
}
127114

128115
internal val homeSectionFingerprint = fingerprint {
129-
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
116+
custom { _, classDef -> classDef.type.endsWith("homeapi/proto/Section;") }
130117
}
131118

132119
internal val homeStructureGetSectionsFingerprint =
133120
structureGetSectionsFingerprint("homeapi/proto/HomeStructure;")
134121

135122
internal val browseSectionFingerprint = fingerprint {
136-
custom { _, classDef-> classDef.endsWith("browsita/v1/resolved/Section;") }
123+
custom { _, classDef-> classDef.type.endsWith("browsita/v1/resolved/Section;") }
137124
}
138125

139126
internal val browseStructureGetSectionsFingerprint =

patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
1414
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
1515
import app.revanced.patcher.util.smali.ExternalLabel
1616
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
17-
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
1817
import app.revanced.util.*
1918
import com.android.tools.smali.dexlib2.Opcode
2019
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@@ -23,7 +22,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
2322
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
2423
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
2524
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
26-
import java.util.logging.Logger
2725

2826
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/misc/UnlockPremiumPatch;"
2927

@@ -78,14 +76,6 @@ val unlockPremiumPatch = bytecodePatch(
7876
}
7977

8078

81-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
82-
Logger.getLogger(this::class.java.name).warning(
83-
"Patching a legacy Spotify version. Patch functionality may be limited."
84-
)
85-
return@execute
86-
}
87-
88-
8979
// Enable choosing a specific song/artist via Google Assistant.
9080
contextFromJsonFingerprint.method.apply {
9181
val insertIndex = contextFromJsonFingerprint.patternMatch!!.startIndex

patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
66
import app.revanced.patcher.patch.bytecodePatch
77
import app.revanced.patcher.patch.stringOption
88
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
9-
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
109
import app.revanced.util.getReference
1110
import app.revanced.util.indexOfFirstInstructionOrThrow
1211
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
@@ -57,16 +56,10 @@ val changeLyricsProviderPatch = bytecodePatch(
5756
}
5857

5958
execute {
60-
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
61-
Logger.getLogger(this::class.java.name).severe(
62-
"Change lyrics provider patch is not supported for this target version."
63-
)
64-
return@execute
65-
}
66-
6759
val httpClientBuilderMethod = httpClientBuilderFingerprint.originalMethod
6860

6961
// region Create a modified copy of the HTTP client builder method with the custom lyrics provider host.
62+
7063
val patchedHttpClientBuilderMethod = with(httpClientBuilderMethod) {
7164
val invokeBuildUrlIndex = indexOfFirstInstructionOrThrow {
7265
getReference<MethodReference>()?.returnType == "Lokhttp3/HttpUrl;"
@@ -89,9 +82,11 @@ val changeLyricsProviderPatch = bytecodePatch(
8982
httpClientBuilderFingerprint.classDef.methods.add(this)
9083
}
9184
}
85+
9286
//endregion
9387

9488
// region Replace the call to the HTTP client builder method used exclusively for lyrics by the modified one.
89+
9590
getLyricsHttpClientFingerprint(httpClientBuilderMethod).method.apply {
9691
val getLyricsHttpClientIndex = indexOfFirstInstructionOrThrow {
9792
getReference<MethodReference>() == httpClientBuilderMethod
@@ -118,6 +113,7 @@ val changeLyricsProviderPatch = bytecodePatch(
118113
)
119114
)
120115
}
116+
121117
//endregion
122118
}
123119
}

patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal val shareCopyUrlFingerprint = fingerprint {
1414
}
1515
}
1616

17-
internal val shareCopyUrlLegacyFingerprint = fingerprint {
17+
internal val oldShareCopyUrlFingerprint = fingerprint {
1818
returns("Ljava/lang/Object;")
1919
parameters("Ljava/lang/Object;")
2020
strings("clipboard", "createNewSession failed")
@@ -38,7 +38,7 @@ internal val formatAndroidShareSheetUrlFingerprint = fingerprint {
3838
}
3939
}
4040

41-
internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint {
41+
internal val oldFormatAndroidShareSheetUrlFingerprint = fingerprint {
4242
accessFlags(AccessFlags.PUBLIC)
4343
returns("Ljava/lang/String;")
4444
parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;")

0 commit comments

Comments
 (0)