Skip to content

Commit

Permalink
fix(YouTube/YT Music - GmsCore support): unimplemented service in Gms…
Browse files Browse the repository at this point in the history
…Core causes memory leak
  • Loading branch information
inotia00 committed Oct 18, 2024
1 parent 1bc0d73 commit f999aea
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package app.revanced.patches.shared.gms

import app.revanced.patcher.PatchClass
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.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
Expand All @@ -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_MUSIC
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.GmsCoreSupportFingerprint
import app.revanced.patches.shared.gms.fingerprints.GmsServiceBrokerFingerprint
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.integrations.Constants.PATCHES_PATH
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.resultOrThrow
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
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.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.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference
import com.android.tools.smali.dexlib2.util.MethodUtil
Expand Down Expand Up @@ -66,11 +71,12 @@ abstract class BaseGmsCoreSupportPatch(
fingerprints = setOf(
// Google Play Services.
CastContextFetchFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
GmsCoreSupportFingerprint,
GmsServiceBrokerFingerprint,
GooglePlayUtilityFingerprint,
PrimeMethodFingerprint,
PrimesApiFingerprint,
PrimesBackgroundInitializationFingerprint,
PrimesLifecycleEventFingerprint,
ServiceCheckFingerprint,

// Signature verification.
Expand Down Expand Up @@ -145,18 +151,16 @@ abstract class BaseGmsCoreSupportPatch(
return@transform null
}

// Specific method that needs to be patched.
transformPrimeMethod(packageName)

// Return these methods early to prevent the app from crashing.
listOf(
CastContextFetchFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
GmsServiceBrokerFingerprint,
GooglePlayUtilityFingerprint,
ServiceCheckFingerprint
).returnEarly()

transformPrimeMethod()

// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
if (checkGmsCore) {
mainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions(
Expand Down Expand Up @@ -285,18 +289,42 @@ abstract class BaseGmsCoreSupportPatch(
}
}

private fun transformPrimeMethod(packageName: String) {
PrimeMethodFingerprint.resultOrThrow().mutableMethod.apply {
var register = 2

val index = getInstructions().indexOfFirst {
if (it.getReference<StringReference>()?.string != fromPackageName) return@indexOfFirst false

register = (it as OneRegisterInstruction).registerA
return@indexOfFirst true
private fun transformPrimeMethod() {
listOf(
PrimesBackgroundInitializationFingerprint,
PrimesLifecycleEventFingerprint
).forEach { fingerprint ->
fingerprint.resultOrThrow().mutableMethod.apply {
val exceptionIndex = indexOfFirstInstructionReversedOrThrow {
opcode == Opcode.NEW_INSTANCE &&
(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\"")
}
}

Expand Down Expand Up @@ -397,6 +425,9 @@ abstract class BaseGmsCoreSupportPatch(
"com.google.android.gms.googlehelp.HELP",
"com.google.android.gms.feedback.internal.IFeedbackService",

// cast
"com.google.android.gms.cast.service.BIND_CAST_DEVICE_CONTROLLER_SERVICE",

// chimera
"com.google.android.gms.chimera",

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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")
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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)
}
)
Original file line number Diff line number Diff line change
@@ -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
}
)
Original file line number Diff line number Diff line change
@@ -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
}
)

0 comments on commit f999aea

Please sign in to comment.