From 161261cfeab4616764d20efe46fcfd483299741c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 2 Dec 2023 22:50:40 +0100 Subject: [PATCH] feat: Allow choosing the vendor of GmsCore via patch options (#3347) BREAKING CHANGE: Various APIs have been moved to `GmsCoreSupportAbstractPatch` --- api/revanced-patches.api | 60 ++-- .../patches/music/misc/gms/Constants.kt | 6 + .../music/misc/gms/GmsCoreSupportPatch.kt | 34 ++ .../misc/gms/GmsCoreSupportResourcePatch.kt | 11 + .../CastDynamiteModuleFingerprint.kt | 2 +- .../CastDynamiteModuleV2Fingerprint.kt | 2 +- .../GooglePlayUtilityFingerprint.kt | 34 +- .../fingerprints/PrimeMethodFingerprint.kt} | 4 +- .../fingerprints/ServiceCheckFingerprint.kt | 29 +- .../music/misc/microg/MicroGBytecodePatch.kt | 70 ---- .../music/misc/microg/MicroGResourcePatch.kt | 40 --- .../music/misc/microg/shared/Constants.kt | 9 - .../misc/gms/AbstractGmsCoreSupportPatch.kt | 308 ++++++++++++++++++ .../AbstractGmsCoreSupportResourcePatch.kt | 112 +++++++ .../fingerprints/GmsCoreSupportFingerprint.kt | 11 + .../patches/youtube/misc/gms/Constants.kt | 6 + .../youtube/misc/gms/GmsCoreSupportPatch.kt | 67 ++++ .../misc/gms/GmsCoreSupportResourcePatch.kt | 33 ++ .../CastContextFetchFingerprint.kt | 2 +- .../CastDynamiteModuleFingerprint.kt | 2 +- .../CastDynamiteModuleV2Fingerprint.kt | 2 +- .../GooglePlayUtilityFingerprint.kt | 2 +- .../fingerprints/PrimeMethodFingerprint.kt} | 14 +- .../fingerprints/ServiceCheckFingerprint.kt | 2 +- .../misc/microg/MicroGBytecodePatch.kt | 79 ----- .../misc/microg/MicroGResourcePatch.kt | 57 ---- .../CastContextFetchFingerprint.kt | 8 - .../youtube/misc/microg/shared/Constants.kt | 9 - .../app/revanced/util/microg/Constants.kt | 130 -------- .../util/microg/MicroGBytecodeHelper.kt | 215 ------------ .../util/microg/MicroGManifestHelper.kt | 58 ---- .../util/microg/MicroGResourceHelper.kt | 63 ---- .../resources/gms/host/values/strings.xml | 5 + .../resources/microg/host/values/strings.xml | 5 - 34 files changed, 678 insertions(+), 813 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/gms/Constants.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch.kt rename src/main/kotlin/app/revanced/patches/music/misc/{microg => gms}/fingerprints/CastDynamiteModuleFingerprint.kt (78%) rename src/main/kotlin/app/revanced/patches/music/misc/{microg => gms}/fingerprints/CastDynamiteModuleV2Fingerprint.kt (75%) rename src/main/kotlin/app/revanced/patches/music/misc/{microg => gms}/fingerprints/GooglePlayUtilityFingerprint.kt (86%) rename src/main/kotlin/app/revanced/patches/{youtube/misc/microg/fingerprints/PrimeFingerprint.kt => music/misc/gms/fingerprints/PrimeMethodFingerprint.kt} (54%) rename src/main/kotlin/app/revanced/patches/music/misc/{microg => gms}/fingerprints/ServiceCheckFingerprint.kt (73%) delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/gms/Constants.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt rename src/main/kotlin/app/revanced/patches/{music/misc/microg => youtube/misc/gms}/fingerprints/CastContextFetchFingerprint.kt (74%) rename src/main/kotlin/app/revanced/patches/youtube/misc/{microg => gms}/fingerprints/CastDynamiteModuleFingerprint.kt (78%) rename src/main/kotlin/app/revanced/patches/youtube/misc/{microg => gms}/fingerprints/CastDynamiteModuleV2Fingerprint.kt (75%) rename src/main/kotlin/app/revanced/patches/youtube/misc/{microg => gms}/fingerprints/GooglePlayUtilityFingerprint.kt (87%) rename src/main/kotlin/app/revanced/patches/{music/misc/microg/fingerprints/PrimeFingerprint.kt => youtube/misc/gms/fingerprints/PrimeMethodFingerprint.kt} (53%) rename src/main/kotlin/app/revanced/patches/youtube/misc/{microg => gms}/fingerprints/ServiceCheckFingerprint.kt (87%) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt create mode 100644 src/main/resources/gms/host/values/strings.xml delete mode 100644 src/main/resources/microg/host/values/strings.xml diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 3d72f40d1..75b395edf 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -309,20 +309,16 @@ public final class app/revanced/patches/music/misc/androidauto/BypassCertificate public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/music/misc/microg/MicroGBytecodePatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/music/misc/microg/MicroGBytecodePatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +public final class app/revanced/patches/music/misc/gms/Constants { + public static final field INSTANCE Lapp/revanced/patches/music/misc/gms/Constants; } -public final class app/revanced/patches/music/misc/microg/MicroGResourcePatch : app/revanced/patcher/patch/ResourcePatch { - public static final field INSTANCE Lapp/revanced/patches/music/misc/microg/MicroGResourcePatch; - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V - public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V +public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch { + public static final field INSTANCE Lapp/revanced/patches/music/misc/gms/GmsCoreSupportPatch; } -public final class app/revanced/patches/music/misc/microg/shared/Constants { - public static final field INSTANCE Lapp/revanced/patches/music/misc/microg/shared/Constants; +public final class app/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch : app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch { + public static final field INSTANCE Lapp/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch; } public final class app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch : app/revanced/patcher/patch/BytecodePatch { @@ -573,6 +569,26 @@ public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalS public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public abstract class app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch : app/revanced/patcher/patch/BytecodePatch { + public fun (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Lapp/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Lapp/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + +public abstract class app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch : app/revanced/patcher/patch/ResourcePatch { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V + protected final fun getGmsCoreVendor ()Ljava/lang/String; +} + +public final class app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { + public static final field GET_GMS_CORE_VENDOR_METHOD_NAME Ljava/lang/String; + public static final field INSTANCE Lapp/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint; +} + public abstract class app/revanced/patches/shared/settings/AbstractSettingsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable { public fun (Ljava/lang/String;Ljava/lang/String;)V public fun close ()V @@ -1394,6 +1410,18 @@ public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignature public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V } +public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + +public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch : app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch; + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V +} + public final class app/revanced/patches/youtube/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/integrations/AbstractIntegrationsPatch { public static final field INSTANCE Lapp/revanced/patches/youtube/misc/integrations/IntegrationsPatch; } @@ -1421,18 +1449,6 @@ public final class app/revanced/patches/youtube/misc/litho/filter/LithoFilterPat public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/youtube/misc/microg/MicroGBytecodePatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V -} - -public final class app/revanced/patches/youtube/misc/microg/MicroGResourcePatch : app/revanced/patcher/patch/ResourcePatch { - public static final field INSTANCE Lapp/revanced/patches/youtube/misc/microg/MicroGResourcePatch; - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V - public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V -} - public final class app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/music/misc/gms/Constants.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/Constants.kt new file mode 100644 index 000000000..f4114a00b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/Constants.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.music.misc.gms + +object Constants { + internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music" + internal const val MUSIC_PACKAGE_NAME = "com.google.android.apps.youtube.music" +} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt new file mode 100644 index 000000000..2d3d241fd --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt @@ -0,0 +1,34 @@ +package app.revanced.patches.music.misc.gms + +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.GmsCoreSupportResourcePatch.gmsCoreVendorOption +import app.revanced.patches.music.misc.gms.fingerprints.* +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportPatch +import app.revanced.patches.youtube.misc.gms.fingerprints.CastContextFetchFingerprint + +@Suppress("unused") +object GmsCoreSupportPatch : AbstractGmsCoreSupportPatch( + fromPackageName = REVANCED_MUSIC_PACKAGE_NAME, + toPackageName = MUSIC_PACKAGE_NAME, + primeMethodFingerprint = PrimeMethodFingerprint, + earlyReturnFingerprints = setOf( + ServiceCheckFingerprint, + GooglePlayUtilityFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + CastContextFetchFingerprint, + ), + abstractGmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, + compatiblePackages = setOf(CompatiblePackage("com.google.android.apps.youtube.music")), + fingerprints = setOf( + ServiceCheckFingerprint, + GooglePlayUtilityFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + CastContextFetchFingerprint, + PrimeMethodFingerprint, + ) +) { + override val gmsCoreVendor by gmsCoreVendorOption +} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..06c36bdef --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportResourcePatch.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.music.misc.gms + +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.shared.misc.gms.AbstractGmsCoreSupportResourcePatch + +object GmsCoreSupportResourcePatch : AbstractGmsCoreSupportResourcePatch( + fromPackageName = MUSIC_PACKAGE_NAME, + toPackageName = REVANCED_MUSIC_PACKAGE_NAME, + spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875" +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt similarity index 78% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt index 26106538d..c1c8ec8cc 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.misc.microg.fingerprints +package app.revanced.patches.music.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt similarity index 75% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt index e9abd3619..0249a9813 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.misc.microg.fingerprints +package app.revanced.patches.music.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt similarity index 86% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt index c2cfb14d5..45b49b345 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt @@ -1,18 +1,18 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal object GooglePlayUtilityFingerprint : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L", "I"), - strings = listOf( - "This should never happen.", - "MetadataValueReader", - "GooglePlayServicesUtil", - "com.android.vending", - "android.hardware.type.embedded" - ) +package app.revanced.patches.music.misc.gms.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object GooglePlayUtilityFingerprint : MethodFingerprint( + "I", + AccessFlags.PUBLIC or AccessFlags.STATIC, + listOf("L", "I"), + strings = listOf( + "This should never happen.", + "MetadataValueReader", + "GooglePlayServicesUtil", + "com.android.vending", + "android.hardware.type.embedded" + ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/PrimeMethodFingerprint.kt similarity index 54% rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/PrimeMethodFingerprint.kt index 00e10d703..2f54a019a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/PrimeMethodFingerprint.kt @@ -1,8 +1,8 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints +package app.revanced.patches.music.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -internal object PrimeFingerprint : 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/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/ServiceCheckFingerprint.kt similarity index 73% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/ServiceCheckFingerprint.kt index 397232cec..ca8db2046 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/fingerprints/ServiceCheckFingerprint.kt @@ -1,15 +1,14 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -internal object ServiceCheckFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L", "I"), - strings = listOf("Google Play Services not available") -) +package app.revanced.patches.music.misc.gms.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + + +internal object ServiceCheckFingerprint : MethodFingerprint( + "V", + AccessFlags.PUBLIC or AccessFlags.STATIC, + listOf("L", "I"), + strings = listOf("Google Play Services not available") +) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt deleted file mode 100644 index 192711a14..000000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGBytecodePatch.kt +++ /dev/null @@ -1,70 +0,0 @@ -package app.revanced.patches.music.misc.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch -import app.revanced.patches.music.misc.microg.fingerprints.* -import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME -import app.revanced.util.microg.MicroGBytecodeHelper - - -@Patch( - name = "Vanced MicroG support", - description = "Allows YouTube Music to run without root and under a different package name.", - dependencies = [ - ChangePackageNamePatch::class, - MicroGResourcePatch::class, - ], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.apps.youtube.music" - ) - ] -) -@Suppress("unused") -object MicroGBytecodePatch : BytecodePatch( - setOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint, - PrimeFingerprint, - ) -) { - // NOTE: the previous patch also replaced the following strings, but it seems like they are not needed: - // - "com.google.android.gms.chimera.GmsIntentOperationService", - // - "com.google.android.gms.phenotype.internal.IPhenotypeCallbacks", - // - "com.google.android.gms.phenotype.internal.IPhenotypeService", - // - "com.google.android.gms.phenotype.PACKAGE_NAME", - // - "com.google.android.gms.phenotype.UPDATE", - // - "com.google.android.gms.phenotype", - override fun execute(context: BytecodeContext) { - val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_MUSIC_PACKAGE_NAME) - - MicroGBytecodeHelper.patchBytecode( - context, - arrayOf( - MicroGBytecodeHelper.packageNameTransform( - MUSIC_PACKAGE_NAME, - packageName - ) - ), - MicroGBytecodeHelper.PrimeMethodTransformationData( - PrimeFingerprint, - MUSIC_PACKAGE_NAME, - packageName - ), - listOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint - ) - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt deleted file mode 100644 index 950fba8d7..000000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/MicroGResourcePatch.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.revanced.patches.music.misc.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch -import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.util.microg.MicroGManifestHelper -import app.revanced.util.microg.MicroGResourceHelper - - -@Patch( - description = "Resource patch to allow YouTube Music ReVanced to run without root " + - "and under a different package name.", - dependencies = [ChangePackageNamePatch::class] -) -object MicroGResourcePatch : ResourcePatch() { - override fun execute(context: ResourceContext) { - val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_MUSIC_PACKAGE_NAME) - - // update manifest - MicroGResourceHelper.patchManifest( - context, - MUSIC_PACKAGE_NAME, - packageName, - REVANCED_MUSIC_APP_NAME - ) - - // add metadata to the manifest - MicroGManifestHelper.addSpoofingMetadata( - context, - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt deleted file mode 100644 index a7405cc4e..000000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.music.misc.microg.shared - -object Constants { - internal const val REVANCED_MUSIC_APP_NAME = "YT Music ReVanced" - internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music" - internal const val MUSIC_PACKAGE_NAME = "com.google.android.apps.youtube.music" - internal const val SPOOFED_PACKAGE_NAME = MUSIC_PACKAGE_NAME - internal const val SPOOFED_PACKAGE_SIGNATURE = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875" -} diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch.kt new file mode 100644 index 000000000..0ea31ed4d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportPatch.kt @@ -0,0 +1,308 @@ +package app.revanced.patches.shared.misc.gms + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.BytecodeContext +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 +import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportPatch.Constants.ACTIONS +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportPatch.Constants.AUTHORITIES +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportPatch.Constants.PERMISSIONS +import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint +import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_METHOD_NAME +import app.revanced.util.exception +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.formats.Instruction21c +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 + +/** + * A patch that allows Google apps to run without root and under a different package name + * by using GmsCore instead of Google Play Services. + * + * @param fromPackageName The package name of the original app. + * @param toPackageName The package name to fall back to if no custom package name is specified in patch options. + * @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched. + * @param earlyReturnFingerprints The fingerprints of methods that need to be returned early. + * @param abstractGmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources. + * @param dependencies Additional dependencies of this patch. + * @param compatiblePackages The compatible packages of this patch. + * @param fingerprints The fingerprints of this patch. + */ +abstract class AbstractGmsCoreSupportPatch( + private val fromPackageName: String, + private val toPackageName: String, + private val primeMethodFingerprint: MethodFingerprint, + private val earlyReturnFingerprints: Set, + abstractGmsCoreSupportResourcePatch: AbstractGmsCoreSupportResourcePatch, + dependencies: Set = setOf(), + compatiblePackages: Set? = null, + fingerprints: Set = emptySet(), +) : BytecodePatch( + name = "GmsCore support", + description = "Allows Google apps to run without root and under a different package name " + + "by using GmsCore instead of Google Play Services.", + dependencies = setOf(ChangePackageNamePatch::class, abstractGmsCoreSupportResourcePatch::class) + dependencies, + compatiblePackages = compatiblePackages, + fingerprints = setOf(GmsCoreSupportFingerprint) + fingerprints, + requiresIntegrations = true +) { + init { + // Manually register all options of the resource patch so that they are visible in the patch API. + abstractGmsCoreSupportResourcePatch.options.values.forEach(options::register) + } + + internal abstract val gmsCoreVendor: String? + + override fun execute(context: BytecodeContext) { + val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName) + + // Transform all strings using all provided transforms, first match wins. + val transformations = arrayOf( + ::commonTransform, + ::contentUrisTransform, + packageNameTransform(fromPackageName, packageName) + ) + context.transformStringReferences transform@{ string -> + transformations.forEach { transform -> + transform(string)?.let { transformedString -> return@transform transformedString } + } + + return@transform null + } + + // Specific method that needs to be patched. + transformPrimeMethod(packageName) + + // Return these methods early to prevent the app from crashing. + earlyReturnFingerprints.toList().returnEarly() + + // Change the vendor of GmsCore in ReVanced Integrations. + GmsCoreSupportFingerprint.result?.mutableClass?.methods + ?.single { it.name == GET_GMS_CORE_VENDOR_METHOD_NAME } + ?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendor\"") + ?: throw GmsCoreSupportFingerprint.exception + } + + private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) = classes.forEach { + val mutableClass by lazy { + proxy(it).mutableClass + } + + it.methods.forEach classLoop@{ methodDef -> + val implementation = methodDef.implementation ?: return@classLoop + + val mutableMethod by lazy { + mutableClass.methods.first { MethodUtil.methodSignaturesMatch(it, methodDef) } + } + + implementation.instructions.forEachIndexed insnLoop@{ index, instruction -> + val string = ((instruction as? Instruction21c)?.reference as? StringReference)?.string + ?: return@insnLoop + + // Apply transformation. + val transformedString = transform(string) ?: return@insnLoop + + mutableMethod.replaceInstruction( + index, + BuilderInstruction21c( + Opcode.CONST_STRING, + instruction.registerA, + ImmutableStringReference(transformedString) + ) + ) + } + } + } + + // region Collection of transformations that are applied to all strings. + + private fun commonTransform(referencedString: String): String? = + when (referencedString) { + "com.google", + "com.google.android.gms", + in PERMISSIONS, + in ACTIONS, + in AUTHORITIES -> referencedString.replace("com.google", gmsCoreVendor!!) + + // No vendor prefix for whatever reason... + "subscribedfeeds" -> "$gmsCoreVendor.subscribedfeeds" + else -> null + } + + private fun contentUrisTransform(str: String): String? { + // only when content:// uri + if (str.startsWith("content://")) { + // check if matches any authority + for (authority in AUTHORITIES) { + val uriPrefix = "content://$authority" + if (str.startsWith(uriPrefix)) { + return str.replace( + uriPrefix, + "content://${authority.replace("com.google", gmsCoreVendor!!)}" + ) + } + } + + // gms also has a 'subscribedfeeds' authority, check for that one too + val subFeedsUriPrefix = "content://subscribedfeeds" + if (str.startsWith(subFeedsUriPrefix)) { + return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendor.subscribedfeeds") + } + } + + return null + + } + + private fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string -> + when (string) { + "$fromPackageName.SuggestionsProvider", + "$fromPackageName.fileprovider" -> string.replace(fromPackageName, toPackageName) + + else -> null + } + } + + private fun transformPrimeMethod(packageName: String) = primeMethodFingerprint.result?.mutableMethod?.apply { + var register = 2 + val index = getInstructions().indexOfFirst { + if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false + + val instructionString = ((it as Instruction21c).reference as StringReference).string + if (instructionString != fromPackageName) return@indexOfFirst false + + register = it.registerA + return@indexOfFirst true + } + + replaceInstruction( + index, "const-string v$register, \"$packageName\"" + ) + } + ?: throw primeMethodFingerprint.exception + + /** + * A collection of permissions, intents and content provider authorities + * that are present in GmsCore which need to be transformed. + * + * NOTE: The following were present, but it seems like they are not needed to be transformed: + * - com.google.android.gms.chimera.GmsIntentOperationService + * - com.google.android.gms.phenotype.internal.IPhenotypeCallbacks + * - com.google.android.gms.phenotype.internal.IPhenotypeService + * - com.google.android.gms.phenotype.PACKAGE_NAME + * - com.google.android.gms.phenotype.UPDATE + * - com.google.android.gms.phenotype + */ + private object Constants { + /** + * A list of all permissions. + */ + val PERMISSIONS = listOf( + // C2DM / GCM + "com.google.android.c2dm.permission.RECEIVE", + "com.google.android.c2dm.permission.SEND", + "com.google.android.gtalkservice.permission.GTALK_SERVICE", + + // GAuth + "com.google.android.googleapps.permission.GOOGLE_AUTH", + "com.google.android.googleapps.permission.GOOGLE_AUTH.cp", + "com.google.android.googleapps.permission.GOOGLE_AUTH.local", + "com.google.android.googleapps.permission.GOOGLE_AUTH.mail", + "com.google.android.googleapps.permission.GOOGLE_AUTH.writely", + ) + + /** + * All intent actions. + */ + val ACTIONS = listOf( + // location + "com.google.android.gms.location.places.ui.PICK_PLACE", + "com.google.android.gms.location.places.GeoDataApi", + "com.google.android.gms.location.places.PlacesApi", + "com.google.android.gms.location.places.PlaceDetectionApi", + "com.google.android.gms.wearable.MESSAGE_RECEIVED", + + // C2DM / GCM + "com.google.android.c2dm.intent.REGISTER", + "com.google.android.c2dm.intent.REGISTRATION", + "com.google.android.c2dm.intent.UNREGISTER", + "com.google.android.c2dm.intent.RECEIVE", + "com.google.iid.TOKEN_REQUEST", + "com.google.android.gcm.intent.SEND", + + // car + "com.google.android.gms.car.service.START", + + // people + "com.google.android.gms.people.service.START", + + // wearable + "com.google.android.gms.wearable.BIND", + + // auth + "com.google.android.gsf.login", + "com.google.android.gsf.action.GET_GLS", + "com.google.android.gms.common.account.CHOOSE_ACCOUNT", + "com.google.android.gms.auth.login.LOGIN", + "com.google.android.gms.auth.api.credentials.PICKER", + "com.google.android.gms.auth.api.credentials.service.START", + "com.google.android.gms.auth.service.START", + "com.google.firebase.auth.api.gms.service.START", + "com.google.android.gms.auth.be.appcert.AppCertService", + + // fido + "com.google.android.gms.fido.fido2.privileged.START", + + // games + "com.google.android.gms.games.service.START", + "com.google.android.gms.games.PLAY_GAMES_UPGRADE", + + // chimera + "com.google.android.gms.chimera", + + // fonts + "com.google.android.gms.fonts", + + // phenotype + "com.google.android.gms.phenotype.service.START", + + // location + "com.google.android.gms.location.reporting.service.START", + + // misc + "com.google.android.gms.gmscompliance.service.START", + "com.google.android.gms.oss.licenses.service.START", + "com.google.android.gms.safetynet.service.START", + "com.google.android.gms.tapandpay.service.BIND" + ) + + /** + * All content provider authorities. + */ + val AUTHORITIES = listOf( + // gsf + "com.google.android.gsf.gservices", + "com.google.settings", + + // auth + "com.google.android.gms.auth.accounts", + + // chimera + "com.google.android.gms.chimera", + + // fonts + "com.google.android.gms.fonts", + + // phenotype + "com.google.android.gms.phenotype" + ) + } + + // endregion +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..72ced135a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/AbstractGmsCoreSupportResourcePatch.kt @@ -0,0 +1,112 @@ +package app.revanced.patches.shared.misc.gms + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption +import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch +import app.revanced.util.mergeStrings +import org.w3c.dom.Element +import org.w3c.dom.Node + +/** + * Abstract resource patch that allows Google apps to run without root and under a different package name + * by using GmsCore instead of Google Play Services. + * + * @param fromPackageName The package name of the original app. + * @param toPackageName The package name to fall back to if no custom package name is specified in patch options. + * @param spoofedPackageSignature The signature of the package to spoof to. + * @param dependencies Additional dependencies of this patch. + */ +abstract class AbstractGmsCoreSupportResourcePatch( + private val fromPackageName: String, + private val toPackageName: String, + private val spoofedPackageSignature: String, + dependencies: Set = setOf() +) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class) + dependencies) { + internal val gmsCoreVendorOption = stringPatchOption( + key = "gmsCoreVendor", + default = "com.mgoogle", + values = mapOf( + "Vanced" to "com.mgoogle", + "ReVanced" to "app.revanced" + ), + title = "GmsCore Vendor", + description = "The group id of the GmsCore vendor.", + required = true + ) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) } + + protected val gmsCoreVendor by gmsCoreVendorOption + + override fun execute(context: ResourceContext) { + context.mergeStrings("gms/host/values/strings.xml") + context.patchManifest() + context.addSpoofingMetadata() + } + + /** + * Add metadata to manifest to support spoofing the package name and signature of GmsCore. + */ + private fun ResourceContext.addSpoofingMetadata() { + fun Node.adoptChild(tagName: String, block: Element.() -> Unit) { + val child = ownerDocument.createElement(tagName) + child.block() + appendChild(child) + } + + xmlEditor["AndroidManifest.xml"].use { + val applicationNode = it + .file + .getElementsByTagName("application") + .item(0) + + // Spoof package name and signature. + applicationNode.adoptChild("meta-data") { + setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_NAME") + setAttribute("android:value", fromPackageName) + } + + applicationNode.adoptChild("meta-data") { + setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_SIGNATURE") + setAttribute("android:value", spoofedPackageSignature) + } + + // GmsCore presence detection in ReVanced Integrations. + applicationNode.adoptChild("meta-data") { + // TODO: The name of this metadata should be dynamic. + setAttribute("android:name", "app.revanced.MICROG_PACKAGE_NAME") + setAttribute("android:value", "$gmsCoreVendor.android.gms") + } + } + } + + /** + * Patch the manifest to support GmsCore. + */ + private fun ResourceContext.patchManifest() { + val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName) + + val manifest = this["AndroidManifest.xml"].readText() + this["AndroidManifest.xml"].writeText( + manifest.replace( + "package=\"$fromPackageName", + "package=\"$packageName" + ).replace( + "android:authorities=\"$fromPackageName", + "android:authorities=\"$packageName" + ).replace( + "$fromPackageName.permission.C2D_MESSAGE", + "$packageName.permission.C2D_MESSAGE" + ).replace( + "$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION", + "$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" + ).replace( + "com.google.android.c2dm", + "$gmsCoreVendor.android.c2dm" + ).replace( + "", + "" + ) + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt new file mode 100644 index 000000000..5ecfa53c6 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.shared.misc.gms.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +object GmsCoreSupportFingerprint : MethodFingerprint( + customFingerprint = { _, classDef -> + classDef.type.endsWith("GmsCoreSupport;") + } +) { + const val GET_GMS_CORE_VENDOR_METHOD_NAME = "getGmsCoreVendor" +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Constants.kt new file mode 100644 index 000000000..c532c57d4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Constants.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.youtube.misc.gms + +internal object Constants { + const val YOUTUBE_PACKAGE_NAME = "com.google.android.youtube" + const val REVANCED_YOUTUBE_PACKAGE_NAME = "app.revanced.android.youtube" +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt new file mode 100644 index 000000000..26f668efb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt @@ -0,0 +1,67 @@ +package app.revanced.patches.youtube.misc.gms + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportPatch +import app.revanced.patches.youtube.layout.buttons.cast.HideCastButtonPatch +import app.revanced.patches.youtube.misc.fix.playback.ClientSpoofPatch +import app.revanced.patches.youtube.misc.gms.Constants.REVANCED_YOUTUBE_PACKAGE_NAME +import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME +import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption +import app.revanced.patches.youtube.misc.gms.fingerprints.* +import app.revanced.patches.youtube.shared.fingerprints.WatchWhileActivityFingerprint +import app.revanced.util.exception + + +@Suppress("unused") +object GmsCoreSupportPatch : AbstractGmsCoreSupportPatch( + fromPackageName = YOUTUBE_PACKAGE_NAME, + toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME, + primeMethodFingerprint = PrimeMethodFingerprint, + earlyReturnFingerprints = setOf( + ServiceCheckFingerprint, + GooglePlayUtilityFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + CastContextFetchFingerprint + ), + dependencies = setOf( + HideCastButtonPatch::class, + ClientSpoofPatch::class + ), + abstractGmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, + compatiblePackages = setOf( + CompatiblePackage( + "com.google.android.youtube", setOf( + "18.32.39", + "18.37.36", + "18.38.44", + "18.43.45", + "18.44.41", + "18.45.41", + "18.45.43" + ) + ) + ), + fingerprints = setOf( + ServiceCheckFingerprint, + GooglePlayUtilityFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + CastContextFetchFingerprint, + PrimeMethodFingerprint, + WatchWhileActivityFingerprint + ) +) { + override val gmsCoreVendor by gmsCoreVendorOption + + override fun execute(context: BytecodeContext) { + // Check the availability of GmsCore. + WatchWhileActivityFingerprint.result?.mutableMethod?.addInstruction( + 0, + "invoke-static {}, Lapp/revanced/integrations/patches/GmsCoreSupport;->checkAvailability()V" + ) ?: throw WatchWhileActivityFingerprint.exception + + super.execute(context) + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..8482704d2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt @@ -0,0 +1,33 @@ +package app.revanced.patches.youtube.misc.gms + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch +import app.revanced.patches.shared.misc.gms.AbstractGmsCoreSupportResourcePatch +import app.revanced.patches.shared.settings.preference.impl.Preference +import app.revanced.patches.shared.settings.preference.impl.StringResource +import app.revanced.patches.youtube.misc.gms.Constants.REVANCED_YOUTUBE_PACKAGE_NAME +import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME +import app.revanced.patches.youtube.misc.settings.SettingsPatch + + +object GmsCoreSupportResourcePatch : AbstractGmsCoreSupportResourcePatch( + fromPackageName = YOUTUBE_PACKAGE_NAME, + toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME, + spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a600", + dependencies = setOf(SettingsPatch::class) +) { + override fun execute(context: ResourceContext) { + SettingsPatch.addPreference( + Preference( + StringResource("microg_settings", "GmsCore Settings"), + StringResource("microg_settings_summary", "Settings for GmsCore"), + Preference.Intent("$gmsCoreVendor.android.gms", "", "org.microg.gms.ui.SettingsActivity") + ) + ) + + val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_YOUTUBE_PACKAGE_NAME) + SettingsPatch.renameIntentsTargetPackage(packageName) + + super.execute(context) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastContextFetchFingerprint.kt similarity index 74% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastContextFetchFingerprint.kt index a15e6a8a0..b2d836fe3 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastContextFetchFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.misc.microg.fingerprints +package app.revanced.patches.youtube.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt similarity index 78% rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt index 722ea085f..783c093c6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints +package app.revanced.patches.youtube.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt similarity index 75% rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt index 64301b9aa..d0a463176 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints +package app.revanced.patches.youtube.misc.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt similarity index 87% rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt index 8393c3ec4..219602aa4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/GooglePlayUtilityFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints +package app.revanced.patches.youtube.misc.gms.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/PrimeMethodFingerprint.kt similarity index 53% rename from src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/PrimeMethodFingerprint.kt index 3e85a6e95..45d39aeec 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/PrimeMethodFingerprint.kt @@ -1,8 +1,8 @@ -package app.revanced.patches.music.misc.microg.fingerprints - - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object PrimeFingerprint : MethodFingerprint( - strings = listOf("com.google.android.GoogleCamera", "com.android.vending") +package app.revanced.patches.youtube.misc.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/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/ServiceCheckFingerprint.kt similarity index 87% rename from src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/ServiceCheckFingerprint.kt index 7c4cf9443..f48de5b41 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/fingerprints/ServiceCheckFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints +package app.revanced.patches.youtube.misc.gms.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt index 48346b60e..e69de29bb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGBytecodePatch.kt @@ -1,79 +0,0 @@ -package app.revanced.patches.youtube.misc.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch -import app.revanced.patches.youtube.shared.fingerprints.WatchWhileActivityFingerprint -import app.revanced.patches.youtube.layout.buttons.cast.HideCastButtonPatch -import app.revanced.patches.youtube.misc.fix.playback.ClientSpoofPatch -import app.revanced.patches.youtube.misc.microg.fingerprints.* -import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME -import app.revanced.util.microg.MicroGBytecodeHelper - -@Patch( - name = "Vanced MicroG support", - description = "Allows YouTube to run without root and under a different package name with Vanced MicroG.", - dependencies = [ - ChangePackageNamePatch::class, - MicroGResourcePatch::class, - HideCastButtonPatch::class, - ClientSpoofPatch::class - ], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", [ - "18.32.39", - "18.37.36", - "18.38.44", - "18.43.45", - "18.44.41", - "18.45.41", - "18.45.43" - ] - ) - ] -) -@Suppress("unused") -object MicroGBytecodePatch : BytecodePatch( - setOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint, - PrimeFingerprint, - WatchWhileActivityFingerprint - ) -) { - override fun execute(context: BytecodeContext) { - val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_PACKAGE_NAME) - - // apply common microG patch - MicroGBytecodeHelper.patchBytecode( - context, arrayOf( - MicroGBytecodeHelper.packageNameTransform( - PACKAGE_NAME, - packageName - ) - ), - MicroGBytecodeHelper.PrimeMethodTransformationData( - PrimeFingerprint, - PACKAGE_NAME, - packageName - ), - listOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint - ) - ) - - // inject the notice for MicroG - MicroGBytecodeHelper.injectNotice(WatchWhileActivityFingerprint) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt deleted file mode 100644 index c38cb0ba2..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/MicroGResourcePatch.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.youtube.misc.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch -import app.revanced.patches.shared.settings.preference.impl.Preference -import app.revanced.patches.shared.settings.preference.impl.StringResource -import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.patches.youtube.misc.settings.SettingsPatch -import app.revanced.util.microg.Constants.MICROG_VENDOR -import app.revanced.util.microg.MicroGManifestHelper -import app.revanced.util.microg.MicroGResourceHelper - -@Patch( - dependencies = [ - SettingsPatch::class, - ChangePackageNamePatch::class - ] -) -object MicroGResourcePatch : ResourcePatch() { - override fun execute(context: ResourceContext) { - SettingsPatch.addPreference( - Preference( - StringResource("microg_settings", "MicroG Settings"), - StringResource("microg_settings_summary", "Settings for MicroG"), - Preference.Intent("$MICROG_VENDOR.android.gms", "", "org.microg.gms.ui.SettingsActivity") - ) - ) - - val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_PACKAGE_NAME) - - SettingsPatch.renameIntentsTargetPackage(packageName) - - // update manifest - MicroGResourceHelper.patchManifest( - context, - PACKAGE_NAME, - packageName, - REVANCED_APP_NAME - ) - - // add metadata to manifest - MicroGManifestHelper.addSpoofingMetadata( - context, - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - - // add strings - MicroGResourceHelper.addStrings(context) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt index c22ff48b6..e69de29bb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt @@ -1,8 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object CastContextFetchFingerprint : MethodFingerprint( - strings = listOf("Error fetching CastContext.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt deleted file mode 100644 index 8aa66d3ce..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.shared - -internal object Constants { - const val REVANCED_APP_NAME = "YouTube ReVanced" - const val REVANCED_PACKAGE_NAME = "app.revanced.android.youtube" - const val PACKAGE_NAME = "com.google.android.youtube" - const val SPOOFED_PACKAGE_NAME = PACKAGE_NAME - const val SPOOFED_PACKAGE_SIGNATURE = "24bb24c05e47e0aefa68a58a766179d9b613a600" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/microg/Constants.kt b/src/main/kotlin/app/revanced/util/microg/Constants.kt deleted file mode 100644 index 912b97561..000000000 --- a/src/main/kotlin/app/revanced/util/microg/Constants.kt +++ /dev/null @@ -1,130 +0,0 @@ -package app.revanced.util.microg - -/** - * constants for microG builds with signature spoofing - */ -internal object Constants { - /** - * microG vendor name - * aka. package prefix / package base - */ - const val MICROG_VENDOR = "com.mgoogle" - - /** - * meta-data for microG package name spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_NAME = "$MICROG_VENDOR.android.gms.SPOOFED_PACKAGE_NAME" - - /** - * meta-data for microG package signature spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_SIGNATURE = "$MICROG_VENDOR.android.gms.SPOOFED_PACKAGE_SIGNATURE" - - /** - * meta-data for microG package detection - */ - const val META_GMS_PACKAGE_NAME = "app.revanced.MICROG_PACKAGE_NAME" - - /** - * a list of all permissions in microG - */ - val PERMISSIONS = listOf( - // C2DM / GCM - "com.google.android.c2dm.permission.RECEIVE", - "com.google.android.c2dm.permission.SEND", - "com.google.android.gtalkservice.permission.GTALK_SERVICE", - - // GAuth - "com.google.android.googleapps.permission.GOOGLE_AUTH", - "com.google.android.googleapps.permission.GOOGLE_AUTH.cp", - "com.google.android.googleapps.permission.GOOGLE_AUTH.local", - "com.google.android.googleapps.permission.GOOGLE_AUTH.mail", - "com.google.android.googleapps.permission.GOOGLE_AUTH.writely", - ) - - /** - * a list of all (intent) actions in microG - */ - val ACTIONS = listOf( - // location - "com.google.android.gms.location.places.ui.PICK_PLACE", - "com.google.android.gms.location.places.GeoDataApi", - "com.google.android.gms.location.places.PlacesApi", - "com.google.android.gms.location.places.PlaceDetectionApi", - "com.google.android.gms.wearable.MESSAGE_RECEIVED", - - // C2DM / GCM - "com.google.android.c2dm.intent.REGISTER", - "com.google.android.c2dm.intent.REGISTRATION", - "com.google.android.c2dm.intent.UNREGISTER", - "com.google.android.c2dm.intent.RECEIVE", - "com.google.iid.TOKEN_REQUEST", - "com.google.android.gcm.intent.SEND", - - // car - "com.google.android.gms.car.service.START", - - // people - "com.google.android.gms.people.service.START", - - // wearable - "com.google.android.gms.wearable.BIND", - - // auth - "com.google.android.gsf.login", - "com.google.android.gsf.action.GET_GLS", - "com.google.android.gms.common.account.CHOOSE_ACCOUNT", - "com.google.android.gms.auth.login.LOGIN", - "com.google.android.gms.auth.api.credentials.PICKER", - "com.google.android.gms.auth.api.credentials.service.START", - "com.google.android.gms.auth.service.START", - "com.google.firebase.auth.api.gms.service.START", - "com.google.android.gms.auth.be.appcert.AppCertService", - - // fido - "com.google.android.gms.fido.fido2.privileged.START", - - // games - "com.google.android.gms.games.service.START", - "com.google.android.gms.games.PLAY_GAMES_UPGRADE", - - // chimera - "com.google.android.gms.chimera", - - // fonts - "com.google.android.gms.fonts", - - // phenotype - "com.google.android.gms.phenotype.service.START", - - // location - "com.google.android.gms.location.reporting.service.START", - - // misc - "com.google.android.gms.gmscompliance.service.START", - "com.google.android.gms.oss.licenses.service.START", - "com.google.android.gms.safetynet.service.START", - "com.google.android.gms.tapandpay.service.BIND" - ) - - /** - * a list of all content provider authorities in microG - */ - val AUTHORITIES = listOf( - // gsf - "com.google.android.gsf.gservices", - "com.google.settings", - - // auth - "com.google.android.gms.auth.accounts", - - // chimera - "com.google.android.gms.chimera", - - // fonts - "com.google.android.gms.fonts", - - // phenotype - "com.google.android.gms.phenotype" - ) -} diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt index 646a146aa..e69de29bb 100644 --- a/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt +++ b/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt @@ -1,215 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.util.returnEarly -import app.revanced.util.microg.Constants.ACTIONS -import app.revanced.util.microg.Constants.AUTHORITIES -import app.revanced.util.microg.Constants.MICROG_VENDOR -import app.revanced.util.microg.Constants.PERMISSIONS -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c -import com.android.tools.smali.dexlib2.iface.reference.StringReference -import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference - -/** - * Helper class for applying bytecode patches needed for the microg-support patches. - */ -internal object MicroGBytecodeHelper { - /** - * Hook a method to check the availability of MicroG. - * - * @param fingerprint The fingerprint of the method to add the call for the notice in. - */ - fun injectNotice(fingerprint: MethodFingerprint) { - fingerprint.result!!.mutableMethod.addInstruction( - 0, - "invoke-static {}, Lapp/revanced/integrations/patches/MicroGSupport;->checkAvailability()V" - ) - } - - /** - * Transform strings with package name out of [fromPackageName] and [toPackageName]. - * - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - **/ - fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? { - return { referencedString -> - when (referencedString) { - "$fromPackageName.SuggestionsProvider", - "$fromPackageName.fileprovider" -> referencedString.replace(fromPackageName, toPackageName) - else -> null - } - } - } - - /** - * Prime method data class for the [MicroGBytecodeHelper] class. - * - * @param primeMethodFingerprint The prime methods [MethodFingerprint]. - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - **/ - data class PrimeMethodTransformationData( - val primeMethodFingerprint: MethodFingerprint, - val fromPackageName: String, - val toPackageName: String - ) { - /** - * Patch the prime method to accept the new package name. - */ - fun transformPrimeMethodPackageName() { - val primeMethod = primeMethodFingerprint.result!!.mutableMethod - val implementation = primeMethod.implementation!! - - var register = 2 - val index = implementation.instructions.indexOfFirst { - if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false - - val instructionString = ((it as Instruction21c).reference as StringReference).string - if (instructionString != fromPackageName) return@indexOfFirst false - - register = it.registerA - return@indexOfFirst true - } - - primeMethod.replaceInstruction( - index, "const-string v$register, \"$toPackageName\"" - ) - } - } - - /** - * Patch the bytecode to work with MicroG. - * Note: this only handles string constants to gms (intent actions, authorities, ...). - * If the app employs additional checks to validate the installed gms package, you'll have to handle those in the app- specific patch - * - * @param context The context. - * @param additionalStringTransforms Additional transformations applied to all const-string references. - * @param primeMethodTransformationData Data to patch the prime method. - * @param earlyReturns List of [MethodFingerprint] to return the resolved methods early. - */ - fun patchBytecode( - context: BytecodeContext, - additionalStringTransforms: Array<(str: String) -> String?>, - primeMethodTransformationData: PrimeMethodTransformationData, - earlyReturns: List - ) { - earlyReturns.returnEarly() - primeMethodTransformationData.transformPrimeMethodPackageName() - - val allTransforms = arrayOf( - MicroGBytecodeHelper::commonTransform, - MicroGBytecodeHelper::contentUrisTransform, - *additionalStringTransforms - ) - - // transform all strings using all provided transforms, first match wins - context.transformStringReferences transform@{ - for (transformFn in allTransforms) { - val s = transformFn(it) - if (s != null) return@transform s - } - - return@transform null - } - } - - /** - * const-string transform function for common gms string references. - * - * @param referencedString The string to transform. - */ - private fun commonTransform(referencedString: String): String? = - when (referencedString) { - "com.google", - "com.google.android.gms", - in PERMISSIONS, - in ACTIONS, - in AUTHORITIES -> referencedString.replace("com.google", MICROG_VENDOR) - - // subscribedfeeds has no vendor prefix for whatever reason... - "subscribedfeeds" -> "${MICROG_VENDOR}.subscribedfeeds" - else -> null - } - - - /** - * const-string transform function for strings containing gms content uris / authorities. - */ - private fun contentUrisTransform(str: String): String? { - // only when content:// uri - if (str.startsWith("content://")) { - // check if matches any authority - for (authority in AUTHORITIES) { - val uriPrefix = "content://$authority" - if (str.startsWith(uriPrefix)) { - return str.replace( - uriPrefix, - "content://${authority.replace("com.google", MICROG_VENDOR)}" - ) - } - } - - // gms also has a 'subscribedfeeds' authority, check for that one too - val subFeedsUriPrefix = "content://subscribedfeeds" - if (str.startsWith(subFeedsUriPrefix)) { - return str.replace(subFeedsUriPrefix, "content://${MICROG_VENDOR}.subscribedfeeds") - } - } - - return null - } - - /** - * Transform all constant string references using a transformation function. - * - * @param transformFn string transformation function. if null, string is not changed. - */ - private fun BytecodeContext.transformStringReferences(transformFn: (str: String) -> String?) { - classes.forEach { classDef -> - var mutableClass: MutableClass? = null - - // enumerate all methods - classDef.methods.forEach classLoop@{ methodDef -> - var mutableMethod: MutableMethod? = null - val implementation = methodDef.implementation ?: return@classLoop - - // enumerate all instructions and find const-string - implementation.instructions.forEachIndexed implLoop@{ index, instruction -> - // skip all that are not const-string - if (instruction.opcode != Opcode.CONST_STRING) return@implLoop - val str = ((instruction as Instruction21c).reference as StringReference).string - - // call transform function - val transformedStr = transformFn(str) - if (transformedStr != null) { - // make class and method mutable, if not already - mutableClass = mutableClass ?: proxy(classDef).mutableClass - mutableMethod = mutableMethod ?: mutableClass!!.methods.first { - it.name == methodDef.name && it.parameterTypes.containsAll(methodDef.parameterTypes) - } - - // replace instruction with updated string - mutableMethod!!.implementation!!.replaceInstruction( - index, - BuilderInstruction21c( - Opcode.CONST_STRING, - instruction.registerA, - ImmutableStringReference( - transformedStr - ) - ) - ) - } - } - } - } - } -} diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt deleted file mode 100644 index 003fa00e3..000000000 --- a/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt +++ /dev/null @@ -1,58 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.util.microg.Constants.META_GMS_PACKAGE_NAME -import app.revanced.util.microg.Constants.META_SPOOFED_PACKAGE_NAME -import app.revanced.util.microg.Constants.META_SPOOFED_PACKAGE_SIGNATURE -import app.revanced.util.microg.Constants.MICROG_VENDOR -import org.w3c.dom.Element -import org.w3c.dom.Node - -/** - * helper class for adding manifest metadata needed for microG builds with signature spoofing - */ -internal object MicroGManifestHelper { - - /** - * Add manifest entries needed for package and signature spoofing when using MicroG. - * Note: this only adds metadata entries for signature spoofing, other changes may still be required to make a microG patch work. - * - * @param context Resource context. - * @param spoofedPackage The package to spoof. - * @param spoofedSignature The signature to spoof. - */ - fun addSpoofingMetadata( - context: ResourceContext, - spoofedPackage: String, - spoofedSignature: String - ) { - context.xmlEditor["AndroidManifest.xml"].use { - val applicationNode = it - .file - .getElementsByTagName("application") - .item(0) - - // package spoofing - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_SPOOFED_PACKAGE_NAME) - setAttribute("android:value", spoofedPackage) - } - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_SPOOFED_PACKAGE_SIGNATURE) - setAttribute("android:value", spoofedSignature) - } - - // microG presence detection in integrations - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_GMS_PACKAGE_NAME) - setAttribute("android:value", "${MICROG_VENDOR}.android.gms") - } - } - } - - private fun Node.adoptChild(tagName: String, block: Element.() -> Unit) { - val child = ownerDocument.createElement(tagName) - child.block() - appendChild(child) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt index 23ff09d82..e69de29bb 100644 --- a/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt +++ b/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt @@ -1,63 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.util.mergeStrings - -/** - * Helper class for applying resource patches needed for the microg-support patches. - */ -internal object MicroGResourceHelper { - - /** - * Add necessary strings to the strings.xml file. - * - * @param context The resource context. - * @param stringsHost The file which hosts the strings. - */ - fun addStrings(context: ResourceContext, stringsHost: String = "microg/host/values/strings.xml") = - context.mergeStrings(stringsHost) - - /** - * Patch the manifest to work with MicroG. - * - * @param context The resource context. - * @param fromPackageName The original package name. - * @param toPackageName The package name to accept. - * @param toName The new name of the app. - */ - fun patchManifest( - context: ResourceContext, - fromPackageName: String, - toPackageName: String, - toName: String - ) { - val manifest = context["AndroidManifest.xml"].readText() - context["AndroidManifest.xml"].writeText( - manifest.replace( - "package=\"$fromPackageName", - "package=\"$toPackageName" - ).replace( - "android:label=\"@string/app_name", - "android:label=\"$toName" - ).replace( - "android:label=\"@string/app_launcher_name", - "android:label=\"$toName" - ).replace( - "android:authorities=\"$fromPackageName", - "android:authorities=\"$toPackageName" - ).replace( - "$fromPackageName.permission.C2D_MESSAGE", - "$toPackageName.permission.C2D_MESSAGE" - ).replace( - "$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION", - "$toPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" - ).replace( - "com.google.android.c2dm", - "${Constants.MICROG_VENDOR}.android.c2dm" - ).replace( - "", - "" - ) - ) - } -} \ No newline at end of file diff --git a/src/main/resources/gms/host/values/strings.xml b/src/main/resources/gms/host/values/strings.xml new file mode 100644 index 000000000..4697165ec --- /dev/null +++ b/src/main/resources/gms/host/values/strings.xml @@ -0,0 +1,5 @@ + + + GmsCore is not installed. Please install it. + GmsCore is failing to run. Please follow the "Don't kill my app" guide for GmsCore. + diff --git a/src/main/resources/microg/host/values/strings.xml b/src/main/resources/microg/host/values/strings.xml deleted file mode 100644 index 6d4c07436..000000000 --- a/src/main/resources/microg/host/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Vanced MicroG is not installed. Please install it. - Vanced MicroG is failing to run. Please follow the "Don't kill my app" guide for Vanced MicroG. -