fix(YouTube/YT Music - GmsCore support): unimplemented service in GmsCore causes memory leak

This commit is contained in:
inotia00 2024-10-18 21:14:21 +09:00
parent 1bc0d73132
commit f999aead6b
8 changed files with 115 additions and 44 deletions

View File

@ -2,9 +2,9 @@ package app.revanced.patches.shared.gms
import app.revanced.patcher.PatchClass import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
@ -15,22 +15,27 @@ import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch.Constants.PERMISS
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC
import app.revanced.patches.shared.gms.fingerprints.CastContextFetchFingerprint import app.revanced.patches.shared.gms.fingerprints.CastContextFetchFingerprint
import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleFingerprint
import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleV2Fingerprint
import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint
import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint
import app.revanced.patches.shared.gms.fingerprints.GmsServiceBrokerFingerprint
import app.revanced.patches.shared.gms.fingerprints.GooglePlayUtilityFingerprint import app.revanced.patches.shared.gms.fingerprints.GooglePlayUtilityFingerprint
import app.revanced.patches.shared.gms.fingerprints.PrimeMethodFingerprint import app.revanced.patches.shared.gms.fingerprints.PrimesApiFingerprint
import app.revanced.patches.shared.gms.fingerprints.PrimesBackgroundInitializationFingerprint
import app.revanced.patches.shared.gms.fingerprints.PrimesLifecycleEventFingerprint
import app.revanced.patches.shared.gms.fingerprints.ServiceCheckFingerprint import app.revanced.patches.shared.gms.fingerprints.ServiceCheckFingerprint
import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
@ -66,11 +71,12 @@ abstract class BaseGmsCoreSupportPatch(
fingerprints = setOf( fingerprints = setOf(
// Google Play Services. // Google Play Services.
CastContextFetchFingerprint, CastContextFetchFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
GmsCoreSupportFingerprint, GmsCoreSupportFingerprint,
GmsServiceBrokerFingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
PrimeMethodFingerprint, PrimesApiFingerprint,
PrimesBackgroundInitializationFingerprint,
PrimesLifecycleEventFingerprint,
ServiceCheckFingerprint, ServiceCheckFingerprint,
// Signature verification. // Signature verification.
@ -145,18 +151,16 @@ abstract class BaseGmsCoreSupportPatch(
return@transform null return@transform null
} }
// Specific method that needs to be patched.
transformPrimeMethod(packageName)
// Return these methods early to prevent the app from crashing. // Return these methods early to prevent the app from crashing.
listOf( listOf(
CastContextFetchFingerprint, CastContextFetchFingerprint,
CastDynamiteModuleFingerprint, GmsServiceBrokerFingerprint,
CastDynamiteModuleV2Fingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
ServiceCheckFingerprint ServiceCheckFingerprint
).returnEarly() ).returnEarly()
transformPrimeMethod()
// Verify GmsCore is installed and whitelisted for power optimizations and background usage. // Verify GmsCore is installed and whitelisted for power optimizations and background usage.
if (checkGmsCore) { if (checkGmsCore) {
mainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions( mainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions(
@ -285,18 +289,42 @@ abstract class BaseGmsCoreSupportPatch(
} }
} }
private fun transformPrimeMethod(packageName: String) { private fun transformPrimeMethod() {
PrimeMethodFingerprint.resultOrThrow().mutableMethod.apply { listOf(
var register = 2 PrimesBackgroundInitializationFingerprint,
PrimesLifecycleEventFingerprint
val index = getInstructions().indexOfFirst { ).forEach { fingerprint ->
if (it.getReference<StringReference>()?.string != fromPackageName) return@indexOfFirst false fingerprint.resultOrThrow().mutableMethod.apply {
val exceptionIndex = indexOfFirstInstructionReversedOrThrow {
register = (it as OneRegisterInstruction).registerA opcode == Opcode.NEW_INSTANCE &&
return@indexOfFirst true (this as? ReferenceInstruction)?.reference?.toString() == "Ljava/lang/IllegalStateException;"
}
val index = indexOfFirstInstructionReversedOrThrow(exceptionIndex, Opcode.IF_EQZ)
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstruction(
index,
"const/4 v$register, 0x1"
)
}
}
PrimesApiFingerprint.resultOrThrow().let {
it.mutableClass.methods.filter { method ->
method.name != "<clinit>" &&
method.returnType == "V"
}.forEach { method ->
method.apply {
val index = if (MethodUtil.isConstructor(method))
indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT &&
getReference<MethodReference>()?.name == "<init>"
} + 1
else 0
addInstruction(
index,
"return-void"
)
}
} }
replaceInstruction(index, "const-string v$register, \"$packageName\"")
} }
} }
@ -397,6 +425,9 @@ abstract class BaseGmsCoreSupportPatch(
"com.google.android.gms.googlehelp.HELP", "com.google.android.gms.googlehelp.HELP",
"com.google.android.gms.feedback.internal.IFeedbackService", "com.google.android.gms.feedback.internal.IFeedbackService",
// cast
"com.google.android.gms.cast.service.BIND_CAST_DEVICE_CONTROLLER_SERVICE",
// chimera // chimera
"com.google.android.gms.chimera", "com.google.android.gms.chimera",

View File

@ -1,7 +0,0 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CastDynamiteModuleFingerprint : MethodFingerprint(
strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
)

View File

@ -1,7 +0,0 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CastDynamiteModuleV2Fingerprint : MethodFingerprint(
strings = listOf("Failed to load module via V2: ")
)

View File

@ -0,0 +1,8 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object GmsServiceBrokerFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf("mServiceBroker is null, client disconnected")
)

View File

@ -1,7 +0,0 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PrimeMethodFingerprint : MethodFingerprint(
strings = listOf("com.google.android.GoogleCamera", "com.android.vending")
)

View File

@ -0,0 +1,12 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.util.MethodUtil
internal object PrimesApiFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf("PrimesApiImpl.java"),
customFingerprint = { methodDef, _ ->
MethodUtil.isConstructor(methodDef)
}
)

View File

@ -0,0 +1,18 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.StringReference
internal object PrimesBackgroundInitializationFingerprint : MethodFingerprint(
opcodes = listOf(Opcode.NEW_INSTANCE),
customFingerprint = { methodDef, _ ->
methodDef.indexOfFirstInstruction {
opcode == Opcode.CONST_STRING &&
getReference<StringReference>()
?.string.toString().startsWith("Primes init triggered from background in package:")
} >= 0
}
)

View File

@ -0,0 +1,23 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
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.StringReference
internal object PrimesLifecycleEventFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(Opcode.NEW_INSTANCE),
customFingerprint = { methodDef, _ ->
methodDef.indexOfFirstInstruction {
opcode == Opcode.CONST_STRING &&
getReference<StringReference>()
?.string.toString().startsWith("Primes did not observe lifecycle events in the expected order.")
} >= 0
}
)