mirror of
https://github.com/revanced/revanced-patches
synced 2024-12-27 10:05:49 +01:00
fix(YouTube Music): Add Spoof client patch
to fix playback (#4132)
This commit is contained in:
parent
3b48f2e5ef
commit
b0925088e8
1
extensions/music/build.gradle.kts
Normal file
1
extensions/music/build.gradle.kts
Normal file
@ -0,0 +1 @@
|
|||||||
|
// Do not remove. Necessary for the extension plugin to be applied to the project.
|
1
extensions/music/src/main/AndroidManifest.xml
Normal file
1
extensions/music/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
@ -0,0 +1,27 @@
|
|||||||
|
package app.revanced.extension.music.spoof;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection unused
|
||||||
|
*/
|
||||||
|
public class SpoofClientPatch {
|
||||||
|
private static final int CLIENT_TYPE_ID = 26;
|
||||||
|
private static final String CLIENT_VERSION = "6.21";
|
||||||
|
private static final String DEVICE_MODEL = "iPhone16,2";
|
||||||
|
private static final String OS_VERSION = "17.7.2.21H221";
|
||||||
|
|
||||||
|
public static int getClientId() {
|
||||||
|
return CLIENT_TYPE_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientVersion() {
|
||||||
|
return CLIENT_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientModel() {
|
||||||
|
return DEVICE_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getOsVersion() {
|
||||||
|
return OS_VERSION;
|
||||||
|
}
|
||||||
|
}
|
@ -324,8 +324,12 @@ public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatchKt {
|
|||||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatchKt {
|
public final class app/revanced/patches/music/misc/spoof/SpoofClientPatchKt {
|
||||||
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/music/misc/spoof/UserAgentClientSpoofPatchKt {
|
||||||
|
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatchKt {
|
public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatchKt {
|
||||||
@ -766,6 +770,10 @@ public final class app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch
|
|||||||
public static synthetic fun spoofVideoStreamsPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
|
public static synthetic fun spoofVideoStreamsPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/shared/misc/spoof/UserAgentClientSpoofPatchKt {
|
||||||
|
public static final fun userAgentClientSpoofPatch (Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatchKt {
|
public final class app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatchKt {
|
||||||
public static final fun getRemoveFileSizeLimitPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getRemoveFileSizeLimitPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,6 @@ import app.revanced.patches.music.misc.extension.hooks.applicationInitHook
|
|||||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||||
|
|
||||||
val sharedExtensionPatch = sharedExtensionPatch(
|
val sharedExtensionPatch = sharedExtensionPatch(
|
||||||
|
"music",
|
||||||
applicationInitHook,
|
applicationInitHook,
|
||||||
)
|
)
|
||||||
|
@ -4,7 +4,7 @@ import app.revanced.patcher.patch.Option
|
|||||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||||
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||||
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
|
import app.revanced.patches.music.misc.spoof.spoofClientPatch
|
||||||
import app.revanced.patches.shared.castContextFetchFingerprint
|
import app.revanced.patches.shared.castContextFetchFingerprint
|
||||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||||
import app.revanced.patches.shared.primeMethodFingerprint
|
import app.revanced.patches.shared.primeMethodFingerprint
|
||||||
@ -21,7 +21,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
|||||||
extensionPatch = sharedExtensionPatch,
|
extensionPatch = sharedExtensionPatch,
|
||||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||||
) {
|
) {
|
||||||
dependsOn(spoofVideoStreamsPatch)
|
dependsOn(spoofClientPatch)
|
||||||
|
|
||||||
compatibleWith(MUSIC_PACKAGE_NAME)
|
compatibleWith(MUSIC_PACKAGE_NAME)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package app.revanced.patches.music.misc.spoof
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal val playerRequestConstructorFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
|
strings("player")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches using the class found in [playerRequestConstructorFingerprint].
|
||||||
|
*/
|
||||||
|
internal val createPlayerRequestBodyFingerprint = fingerprint {
|
||||||
|
parameters("L")
|
||||||
|
returns("V")
|
||||||
|
opcodes(
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.AND_INT_LIT16,
|
||||||
|
)
|
||||||
|
strings("ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get a reference to other clientInfo fields.
|
||||||
|
*/
|
||||||
|
internal val setClientInfoFieldsFingerprint = fingerprint {
|
||||||
|
returns("L")
|
||||||
|
strings("Google Inc.")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get a reference to the clientInfo and clientInfo.clientVersion field.
|
||||||
|
*/
|
||||||
|
internal val setClientInfoClientVersionFingerprint = fingerprint {
|
||||||
|
strings("10.29")
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package app.revanced.patches.music.misc.spoof
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
|
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||||
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
|
|
||||||
|
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
|
"Lapp/revanced/extension/music/spoof/SpoofClientPatch;"
|
||||||
|
|
||||||
|
// TODO: Replace this patch with spoofVideoStreamsPatch once possible.
|
||||||
|
val spoofClientPatch = bytecodePatch(
|
||||||
|
name = "Spoof client",
|
||||||
|
description = "Spoofs the client to fix playback.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.google.android.apps.youtube.music")
|
||||||
|
|
||||||
|
dependsOn(
|
||||||
|
sharedExtensionPatch,
|
||||||
|
// TODO: Add settingsPatch
|
||||||
|
userAgentClientSpoofPatch,
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
val playerRequestClass = playerRequestConstructorFingerprint.classDef
|
||||||
|
|
||||||
|
val createPlayerRequestBodyMatch = createPlayerRequestBodyFingerprint.match(playerRequestClass)
|
||||||
|
|
||||||
|
val clientInfoContainerClass = createPlayerRequestBodyMatch.method
|
||||||
|
.getInstruction(createPlayerRequestBodyMatch.patternMatch!!.startIndex)
|
||||||
|
.getReference<TypeReference>()!!.type
|
||||||
|
|
||||||
|
val clientInfoField = setClientInfoClientVersionFingerprint.method.instructions.first {
|
||||||
|
it.opcode == Opcode.IPUT_OBJECT && it.getReference<FieldReference>()!!.definingClass == clientInfoContainerClass
|
||||||
|
}.getReference<FieldReference>()!!
|
||||||
|
|
||||||
|
val setClientInfoFieldInstructions = setClientInfoFieldsFingerprint.method.instructions.filter {
|
||||||
|
(it.opcode == Opcode.IPUT_OBJECT || it.opcode == Opcode.IPUT) &&
|
||||||
|
it.getReference<FieldReference>()!!.definingClass == clientInfoField.type
|
||||||
|
}.map { it.getReference<FieldReference>()!! }
|
||||||
|
|
||||||
|
// Offsets are known for the fields in the clientInfo object.
|
||||||
|
val clientIdField = setClientInfoFieldInstructions[0]
|
||||||
|
val clientModelField = setClientInfoFieldInstructions[5]
|
||||||
|
val osVersionField = setClientInfoFieldInstructions[7]
|
||||||
|
val clientVersionField = setClientInfoClientVersionFingerprint.method
|
||||||
|
.getInstruction(setClientInfoClientVersionFingerprint.stringMatches!!.first().index + 1)
|
||||||
|
.getReference<FieldReference>()
|
||||||
|
|
||||||
|
// Helper method to spoof the client info.
|
||||||
|
val spoofClientInfoMethod = ImmutableMethod(
|
||||||
|
playerRequestClass.type,
|
||||||
|
"spoofClientInfo",
|
||||||
|
listOf(ImmutableMethodParameter(clientInfoContainerClass, null, null)),
|
||||||
|
"V",
|
||||||
|
AccessFlags.PRIVATE.value or AccessFlags.STATIC.value,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
MutableMethodImplementation(3),
|
||||||
|
).toMutable().also(playerRequestClass.methods::add).apply {
|
||||||
|
addInstructions(
|
||||||
|
"""
|
||||||
|
iget-object v0, p0, $clientInfoField
|
||||||
|
|
||||||
|
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientId()I
|
||||||
|
move-result v1
|
||||||
|
iput v1, v0, $clientIdField
|
||||||
|
|
||||||
|
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientModel()Ljava/lang/String;
|
||||||
|
move-result-object v1
|
||||||
|
iput-object v1, v0, $clientModelField
|
||||||
|
|
||||||
|
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientVersion()Ljava/lang/String;
|
||||||
|
move-result-object v1
|
||||||
|
iput-object v1, v0, $clientVersionField
|
||||||
|
|
||||||
|
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getOsVersion()Ljava/lang/String;
|
||||||
|
move-result-object v1
|
||||||
|
iput-object v1, v0, $osVersionField
|
||||||
|
|
||||||
|
return-void
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
createPlayerRequestBodyMatch.method.apply {
|
||||||
|
val checkCastIndex = createPlayerRequestBodyMatch.patternMatch!!.startIndex
|
||||||
|
val clientInfoContainerRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||||
|
|
||||||
|
addInstruction(checkCastIndex + 1, "invoke-static {v$clientInfoContainerRegister}, $spoofClientInfoMethod")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
package app.revanced.patches.music.misc.spoof
|
|
||||||
|
|
||||||
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
|
|
||||||
|
|
||||||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
|
||||||
compatibleWith("com.google.android.apps.youtube.music")
|
|
||||||
})
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package app.revanced.patches.music.misc.spoof
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.spoof.userAgentClientSpoofPatch
|
||||||
|
|
||||||
|
val userAgentClientSpoofPatch = userAgentClientSpoofPatch("com.google.android.apps.youtube.music")
|
@ -0,0 +1,81 @@
|
|||||||
|
package app.revanced.patches.shared.misc.spoof
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||||
|
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
|
||||||
|
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||||
|
|
||||||
|
private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE =
|
||||||
|
"Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;"
|
||||||
|
|
||||||
|
fun userAgentClientSpoofPatch(originalPackageName: String) = transformInstructionsPatch(
|
||||||
|
filterMap = { classDef, _, instruction, instructionIndex ->
|
||||||
|
filterMapInstruction35c<MethodCall>(
|
||||||
|
"Lapp/revanced/extension",
|
||||||
|
classDef,
|
||||||
|
instruction,
|
||||||
|
instructionIndex,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
transform = transform@{ mutableMethod, entry ->
|
||||||
|
val (_, _, instructionIndex) = entry
|
||||||
|
|
||||||
|
// Replace the result of context.getPackageName(), if it is used in a user agent string.
|
||||||
|
mutableMethod.apply {
|
||||||
|
// After context.getPackageName() the result is moved to a register.
|
||||||
|
val targetRegister = (
|
||||||
|
getInstruction(instructionIndex + 1)
|
||||||
|
as? OneRegisterInstruction ?: return@transform
|
||||||
|
).registerA
|
||||||
|
|
||||||
|
// IndexOutOfBoundsException is technically possible here,
|
||||||
|
// but no such occurrences are present in the app.
|
||||||
|
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()
|
||||||
|
|
||||||
|
// Only replace string builder usage.
|
||||||
|
if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) {
|
||||||
|
return@transform
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not change the package name in methods that use resources, or for methods that use GmsCore.
|
||||||
|
// Changing these package names will result in playback limitations,
|
||||||
|
// particularly Android VR background audio only playback.
|
||||||
|
val resourceOrGmsStringInstructionIndex = indexOfFirstInstruction {
|
||||||
|
val reference = getReference<StringReference>()
|
||||||
|
opcode == Opcode.CONST_STRING &&
|
||||||
|
(reference?.string == "android.resource://" || reference?.string == "gcore_")
|
||||||
|
}
|
||||||
|
if (resourceOrGmsStringInstructionIndex >= 0) {
|
||||||
|
return@transform
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the result of context.getPackageName() with the original package name.
|
||||||
|
replaceInstruction(
|
||||||
|
instructionIndex + 1,
|
||||||
|
"const-string v$targetRegister, \"$originalPackageName\"",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
private enum class MethodCall(
|
||||||
|
override val definedClassName: String,
|
||||||
|
override val methodName: String,
|
||||||
|
override val methodParams: Array<String>,
|
||||||
|
override val returnType: String,
|
||||||
|
) : IMethodCall {
|
||||||
|
GetPackageName(
|
||||||
|
"Landroid/content/Context;",
|
||||||
|
"getPackageName",
|
||||||
|
emptyArray(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
}
|
@ -1,82 +1,5 @@
|
|||||||
package app.revanced.patches.youtube.misc.spoof
|
package app.revanced.patches.youtube.misc.spoof
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patches.shared.misc.spoof.userAgentClientSpoofPatch
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|
||||||
import app.revanced.patches.all.misc.transformation.IMethodCall
|
|
||||||
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
|
|
||||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
|
||||||
import app.revanced.util.getReference
|
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
|
||||||
|
|
||||||
private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
|
val userAgentClientSpoofPatch = userAgentClientSpoofPatch("com.google.android.youtube")
|
||||||
private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE =
|
|
||||||
"Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;"
|
|
||||||
|
|
||||||
val userAgentClientSpoofPatch = transformInstructionsPatch(
|
|
||||||
filterMap = { classDef, _, instruction, instructionIndex ->
|
|
||||||
filterMapInstruction35c<MethodCall>(
|
|
||||||
"Lapp/revanced/extension",
|
|
||||||
classDef,
|
|
||||||
instruction,
|
|
||||||
instructionIndex,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
transform = transform@{ mutableMethod, entry ->
|
|
||||||
val (_, _, instructionIndex) = entry
|
|
||||||
|
|
||||||
// Replace the result of context.getPackageName(), if it is used in a user agent string.
|
|
||||||
mutableMethod.apply {
|
|
||||||
// After context.getPackageName() the result is moved to a register.
|
|
||||||
val targetRegister = (
|
|
||||||
getInstruction(instructionIndex + 1)
|
|
||||||
as? OneRegisterInstruction ?: return@transform
|
|
||||||
).registerA
|
|
||||||
|
|
||||||
// IndexOutOfBoundsException is technically possible here,
|
|
||||||
// but no such occurrences are present in the app.
|
|
||||||
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()
|
|
||||||
|
|
||||||
// Only replace string builder usage.
|
|
||||||
if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) {
|
|
||||||
return@transform
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not change the package name in methods that use resources, or for methods that use GmsCore.
|
|
||||||
// Changing these package names will result in playback limitations,
|
|
||||||
// particularly Android VR background audio only playback.
|
|
||||||
val resourceOrGmsStringInstructionIndex = indexOfFirstInstruction {
|
|
||||||
val reference = getReference<StringReference>()
|
|
||||||
opcode == Opcode.CONST_STRING &&
|
|
||||||
(reference?.string == "android.resource://" || reference?.string == "gcore_")
|
|
||||||
}
|
|
||||||
if (resourceOrGmsStringInstructionIndex >= 0) {
|
|
||||||
return@transform
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite the result of context.getPackageName() with the original package name.
|
|
||||||
replaceInstruction(
|
|
||||||
instructionIndex + 1,
|
|
||||||
"const-string v$targetRegister, \"$ORIGINAL_PACKAGE_NAME\"",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
private enum class MethodCall(
|
|
||||||
override val definedClassName: String,
|
|
||||||
override val methodName: String,
|
|
||||||
override val methodParams: Array<String>,
|
|
||||||
override val returnType: String,
|
|
||||||
) : IMethodCall {
|
|
||||||
GetPackageName(
|
|
||||||
"Landroid/content/Context;",
|
|
||||||
"getPackageName",
|
|
||||||
emptyArray(),
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user