diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt index 394b4114e4..314a845987 100644 --- a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt @@ -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 @@ -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 @@ -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. @@ -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( @@ -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()?.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(index).registerA + addInstruction( + index, + "const/4 v$register, 0x1" + ) + } + } + PrimesApiFingerprint.resultOrThrow().let { + it.mutableClass.methods.filter { method -> + method.name != "" && + method.returnType == "V" + }.forEach { method -> + method.apply { + val index = if (MethodUtil.isConstructor(method)) + indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_DIRECT && + getReference()?.name == "" + } + 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.feedback.internal.IFeedbackService", + // cast + "com.google.android.gms.cast.service.BIND_CAST_DEVICE_CONTROLLER_SERVICE", + // chimera "com.google.android.gms.chimera", diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt deleted file mode 100644 index b109574dc2..0000000000 --- a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt +++ /dev/null @@ -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") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt deleted file mode 100644 index a00275974f..0000000000 --- a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ /dev/null @@ -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: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsServiceBrokerFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsServiceBrokerFingerprint.kt new file mode 100644 index 0000000000..853480b7e5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsServiceBrokerFingerprint.kt @@ -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") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt deleted file mode 100644 index 1517b011a5..0000000000 --- a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt +++ /dev/null @@ -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") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesApiFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesApiFingerprint.kt new file mode 100644 index 0000000000..e55f5e824a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesApiFingerprint.kt @@ -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) + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesBackgroundInitializationFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesBackgroundInitializationFingerprint.kt new file mode 100644 index 0000000000..78f05a7ca8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesBackgroundInitializationFingerprint.kt @@ -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() + ?.string.toString().startsWith("Primes init triggered from background in package:") + } >= 0 + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesLifecycleEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesLifecycleEventFingerprint.kt new file mode 100644 index 0000000000..70fa68a57a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimesLifecycleEventFingerprint.kt @@ -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() + ?.string.toString().startsWith("Primes did not observe lifecycle events in the expected order.") + } >= 0 + } +) \ No newline at end of file