From 19adea7a86a20ef2deb6bee168b1145045bbc716 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Mon, 1 Apr 2024 09:25:11 +0900 Subject: [PATCH] feat(GmsCore support): switch to ReVanced GmsCore vendor --- .../fix/fileprovider/FileProviderPatch.kt | 8 +- .../music/utils/gms/GmsCoreSupportPatch.kt | 35 ++ .../utils/gms/GmsCoreSupportResourcePatch.kt | 32 ++ .../mainactivity/MainActivityResolvePatch.kt | 2 +- .../patches/music/utils/microg/Constants.kt | 8 - .../patches/music/utils/microg/MicroGPatch.kt | 105 ------ .../music/utils/microg/MicroGResourcePatch.kt | 56 --- .../GooglePlayUtilityFingerprint.kt | 18 - .../music/utils/settings/ResourceUtils.kt | 12 +- .../utils/sponsorblock/SponsorBlockPatch.kt | 2 +- .../shared/gms/BaseGmsCoreSupportPatch.kt | 341 ++++++++++++++++++ .../gms/BaseGmsCoreSupportResourcePatch.kt | 103 ++++++ .../CastContextFetchFingerprint.kt | 2 +- .../CastDynamiteModuleFingerprint.kt | 2 +- .../CastDynamiteModuleV2Fingerprint.kt | 2 +- .../fingerprints/GmsCoreSupportFingerprint.kt | 11 + .../GooglePlayUtilityFingerprint.kt | 5 +- .../fingerprints/PrimeMethodFingerprint.kt} | 4 +- .../fingerprints/ServiceCheckFingerprint.kt | 2 +- .../patches/shared/microg/Constants.kt | 136 ------- .../shared/microg/MicroGBytecodeHelper.kt | 241 ------------- .../shared/microg/MicroGManifestHelper.kt | 57 --- .../shared/microg/MicroGResourceHelper.kt | 66 ---- .../shared/packagename/PackageNamePatch.kt | 25 +- .../general/OverlayButtonsPatch.kt | 2 - .../parameter/SpoofPlayerParameterPatch.kt | 4 +- .../youtube/utils/gms/GmsCoreSupportPatch.kt | 47 +++ .../utils/gms/GmsCoreSupportResourcePatch.kt | 33 ++ .../patches/youtube/utils/microg/Constants.kt | 7 - .../utils/microg/MicroGBytecodePatch.kt | 75 ---- .../youtube/utils/microg/MicroGPatch.kt | 97 ----- .../CastContextFetchFingerprint.kt | 7 - .../CastDynamiteModuleFingerprint.kt | 7 - .../CastDynamiteModuleV2Fingerprint.kt | 7 - .../microg/fingerprints/PrimeFingerprint.kt | 7 - .../fingerprints/ServiceCheckFingerprint.kt | 15 - .../youtube/utils/settings/ResourceUtils.kt | 23 +- .../kotlin/app/revanced/util/BytecodeUtils.kt | 26 ++ .../music/settings/host/values/strings.xml | 12 +- .../youtube/settings/host/values/strings.xml | 12 +- .../youtube/settings/xml/revanced_prefs.xml | 10 +- 41 files changed, 709 insertions(+), 957 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/utils/microg/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportResourcePatch.kt rename src/main/kotlin/app/revanced/patches/{music/utils/microg => shared/gms}/fingerprints/CastContextFetchFingerprint.kt (73%) rename src/main/kotlin/app/revanced/patches/{music/utils/microg => shared/gms}/fingerprints/CastDynamiteModuleFingerprint.kt (77%) rename src/main/kotlin/app/revanced/patches/{music/utils/microg => shared/gms}/fingerprints/CastDynamiteModuleV2Fingerprint.kt (74%) create mode 100644 src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsCoreSupportFingerprint.kt rename src/main/kotlin/app/revanced/patches/{youtube/utils/microg => shared/gms}/fingerprints/GooglePlayUtilityFingerprint.kt (75%) rename src/main/kotlin/app/revanced/patches/{music/utils/microg/fingerprints/PrimeFingerprint.kt => shared/gms/fingerprints/PrimeMethodFingerprint.kt} (56%) rename src/main/kotlin/app/revanced/patches/{music/utils/microg => shared/gms}/fingerprints/ServiceCheckFingerprint.kt (86%) delete mode 100644 src/main/kotlin/app/revanced/patches/shared/microg/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/patches/shared/microg/MicroGBytecodeHelper.kt delete mode 100644 src/main/kotlin/app/revanced/patches/shared/microg/MicroGManifestHelper.kt delete mode 100644 src/main/kotlin/app/revanced/patches/shared/microg/MicroGResourceHelper.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastContextFetchFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/PrimeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/ServiceCheckFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/fileprovider/FileProviderPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/fileprovider/FileProviderPatch.kt index d735bc134..31e762987 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/fileprovider/FileProviderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/fix/fileprovider/FileProviderPatch.kt @@ -4,7 +4,6 @@ import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.utils.fix.fileprovider.fingerprints.FileProviderResolverFingerprint @@ -17,11 +16,8 @@ object FileProviderPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext) { - val youtubePackageName = PackageNamePatch.PackageNameYouTube - ?: throw PatchException("Invalid package name.") - - val musicPackageName = PackageNamePatch.PackageNameYouTubeMusic - ?: throw PatchException("Invalid package name.") + val youtubePackageName = PackageNamePatch.packageNameYouTube + val musicPackageName = PackageNamePatch.packageNameYouTubeMusic /** * For some reason, if the app gets "android.support.FILE_PROVIDER_PATHS", diff --git a/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportPatch.kt new file mode 100644 index 000000000..38fbb606e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportPatch.kt @@ -0,0 +1,35 @@ +package app.revanced.patches.music.utils.gms + +import app.revanced.patches.music.utils.fix.clientspoof.ClientSpoofPatch +import app.revanced.patches.music.utils.fix.fileprovider.FileProviderPatch +import app.revanced.patches.music.utils.integrations.IntegrationsPatch +import app.revanced.patches.music.utils.mainactivity.fingerprints.MainActivityFingerprint +import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch +import app.revanced.patches.shared.packagename.PackageNamePatch +import app.revanced.patches.shared.packagename.PackageNamePatch.ORIGINAL_PACKAGE_NAME_YOUTUBE + +@Suppress("unused") +object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( + fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE, + mainActivityOnCreateFingerprint = MainActivityFingerprint, + integrationsPatchDependency = IntegrationsPatch::class, + dependencies = setOf(ClientSpoofPatch::class, PackageNamePatch::class, FileProviderPatch::class), + gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, + compatiblePackages = setOf( + CompatiblePackage( + "com.google.android.apps.youtube.music", + setOf( + "6.21.52", + "6.22.52", + "6.23.56", + "6.25.53", + "6.26.51", + "6.27.54", + "6.28.53", + "6.29.58", + "6.31.55", + "6.33.52" + ), + ), + ) +) diff --git a/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..266c663d3 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/utils/gms/GmsCoreSupportResourcePatch.kt @@ -0,0 +1,32 @@ +package app.revanced.patches.music.utils.gms + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patches.music.utils.settings.CategoryType +import app.revanced.patches.music.utils.settings.ResourceUtils.addMicroGPreference +import app.revanced.patches.music.utils.settings.ResourceUtils.updatePackageName +import app.revanced.patches.music.utils.settings.SettingsPatch +import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch +import app.revanced.patches.shared.packagename.PackageNamePatch +import app.revanced.patches.shared.packagename.PackageNamePatch.ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC + +object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch( + fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC, + spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875", + dependencies = setOf(PackageNamePatch::class, SettingsPatch::class), +) { + private const val GMS_CORE_PACKAGE_NAME = "app.revanced.android.gms" + private const val GMS_CORE_SETTINGS_ACTIVITY = "org.microg.gms.ui.SettingsActivity" + + override fun execute(context: ResourceContext) { + super.execute(context) + + context.updatePackageName(PackageNamePatch.packageNameYouTubeMusic) + + context.addMicroGPreference( + CategoryType.MISC.value, + "gms_core_settings", + GMS_CORE_PACKAGE_NAME, + GMS_CORE_SETTINGS_ACTIVITY + ) + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/utils/mainactivity/MainActivityResolvePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/mainactivity/MainActivityResolvePatch.kt index 750f89e74..ca844fea2 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/mainactivity/MainActivityResolvePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/mainactivity/MainActivityResolvePatch.kt @@ -29,7 +29,7 @@ object MainActivityResolvePatch : BytecodePatch( onCreateMethod.apply { addInstruction( 2, - "invoke-static/range {p0 .. p0}, $UTILS_PATH/$methods;->$descriptor(Landroid/content/Context;)V" + "invoke-static/range {p0 .. p0}, $UTILS_PATH/$methods;->$descriptor(Landroid/app/Activity;)V" ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/Constants.kt b/src/main/kotlin/app/revanced/patches/music/utils/microg/Constants.kt deleted file mode 100644 index e42596eda..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/Constants.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.music.utils.microg - -object Constants { - internal const val YOUTUBE_PACKAGE_NAME = "com.google.android.youtube" - 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" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGPatch.kt deleted file mode 100644 index 941a83b04..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGPatch.kt +++ /dev/null @@ -1,105 +0,0 @@ -package app.revanced.patches.music.utils.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.utils.fix.clientspoof.ClientSpoofPatch -import app.revanced.patches.music.utils.fix.fileprovider.FileProviderPatch -import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch -import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch.injectInit -import app.revanced.patches.music.utils.microg.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.utils.microg.Constants.YOUTUBE_PACKAGE_NAME -import app.revanced.patches.music.utils.microg.fingerprints.CastContextFetchFingerprint -import app.revanced.patches.music.utils.microg.fingerprints.CastDynamiteModuleFingerprint -import app.revanced.patches.music.utils.microg.fingerprints.CastDynamiteModuleV2Fingerprint -import app.revanced.patches.music.utils.microg.fingerprints.GooglePlayUtilityFingerprint -import app.revanced.patches.music.utils.microg.fingerprints.PrimeFingerprint -import app.revanced.patches.music.utils.microg.fingerprints.ServiceCheckFingerprint -import app.revanced.patches.shared.microg.MicroGBytecodeHelper -import app.revanced.patches.shared.packagename.PackageNamePatch - -@Patch( - name = "MicroG support", - description = "Allows YouTube Music to run without root and under a different package name with MicroG.", - dependencies = [ - ClientSpoofPatch::class, - MainActivityResolvePatch::class, - MicroGResourcePatch::class, - PackageNamePatch::class, - FileProviderPatch::class - ], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.apps.youtube.music", - [ - "6.21.52", - "6.22.52", - "6.23.56", - "6.25.53", - "6.26.51", - "6.27.54", - "6.28.53", - "6.29.58", - "6.31.55", - "6.33.52" - ] - ) - ] -) -@Suppress("unused") -object MicroGPatch : BytecodePatch( - setOf( - CastContextFetchFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - GooglePlayUtilityFingerprint, - PrimeFingerprint, - ServiceCheckFingerprint - ) -) { - // 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 youtubePackageName = PackageNamePatch.PackageNameYouTube - ?: throw PatchException("Invalid package name.") - - val musicPackageName = PackageNamePatch.PackageNameYouTubeMusic - ?: throw PatchException("Invalid package name.") - - if (youtubePackageName == YOUTUBE_PACKAGE_NAME || musicPackageName == MUSIC_PACKAGE_NAME) - throw PatchException("Original package name is not available as package name for MicroG build.") - - // apply common microG patch - MicroGBytecodeHelper.patchBytecode( - context, - arrayOf( - MicroGBytecodeHelper.packageNameTransform( - YOUTUBE_PACKAGE_NAME, - youtubePackageName - ) - ), - MicroGBytecodeHelper.PrimeMethodTransformationData( - PrimeFingerprint, - MUSIC_PACKAGE_NAME, - musicPackageName - ), - listOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint - ) - ) - - injectInit("MicroGPatch", "checkAvailability") - - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGResourcePatch.kt deleted file mode 100644 index 1ee1b1197..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/MicroGResourcePatch.kt +++ /dev/null @@ -1,56 +0,0 @@ -package app.revanced.patches.music.utils.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.utils.microg.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.utils.microg.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.music.utils.microg.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.patches.music.utils.settings.CategoryType -import app.revanced.patches.music.utils.settings.ResourceUtils.addMicroGPreference -import app.revanced.patches.music.utils.settings.ResourceUtils.setMicroG -import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.patches.shared.microg.Constants.MICROG_PACKAGE_NAME -import app.revanced.patches.shared.microg.MicroGManifestHelper.addSpoofingMetadata -import app.revanced.patches.shared.microg.MicroGResourceHelper.patchManifest -import app.revanced.patches.shared.packagename.PackageNamePatch - -@Patch( - dependencies = [ - PackageNamePatch::class, - SettingsPatch::class - ] -) -object MicroGResourcePatch : ResourcePatch() { - private const val MICROG_TARGET_CLASS = "org.microg.gms.ui.SettingsActivity" - override fun execute(context: ResourceContext) { - val packageName = PackageNamePatch.PackageNameYouTubeMusic - ?: throw PatchException("Invalid package name.") - - if (packageName == MUSIC_PACKAGE_NAME) - throw PatchException("Original package name is not available as package name for MicroG build.") - - // update manifest - context.patchManifest( - MUSIC_PACKAGE_NAME, - packageName - ) - - // add metadata to the manifest - context.addSpoofingMetadata( - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - - context.setMicroG(packageName) - - context.addMicroGPreference( - CategoryType.MISC.value, - "microg_settings", - MICROG_PACKAGE_NAME, - MICROG_TARGET_CLASS - ) - - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt deleted file mode 100644 index 5a12ceb94..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.music.utils.microg.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -object GooglePlayUtilityFingerprint : MethodFingerprint( - returnType = "I", - accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, - parameters = 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/music/utils/settings/ResourceUtils.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/ResourceUtils.kt index 0cb7718ba..10cc39358 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/ResourceUtils.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/ResourceUtils.kt @@ -7,7 +7,7 @@ import app.revanced.util.doRecursively import app.revanced.util.insertNode import org.w3c.dom.Element -@Suppress("MemberVisibilityCanBePrivate") +@Suppress("DEPRECATION", "MemberVisibilityCanBePrivate") object ResourceUtils { const val YOUTUBE_MUSIC_SETTINGS_PATH = "res/xml/settings_headers.xml" @@ -25,10 +25,10 @@ object ResourceUtils { const val YOUTUBE_MUSIC_PREFERENCE_TARGET_CLASS = "com.google.android.gms.common.api.GoogleApiActivity" - var targetPackage = "com.google.android.apps.youtube.music" + var musicPackageName = "com.google.android.apps.youtube.music" - fun ResourceContext.setMicroG(newPackage: String) { - targetPackage = newPackage + fun ResourceContext.updatePackageName(newPackage: String) { + musicPackageName = newPackage replacePackageName() } @@ -86,7 +86,7 @@ object ResourceUtils { fun ResourceContext.replacePackageName() { this[YOUTUBE_MUSIC_SETTINGS_PATH].writeText( this[YOUTUBE_MUSIC_SETTINGS_PATH].readText() - .replace("\"com.google.android.apps.youtube.music\"", "\"" + targetPackage + "\"") + .replace("\"com.google.android.apps.youtube.music\"", "\"" + musicPackageName + "\"") ) } @@ -159,7 +159,7 @@ object ResourceUtils { setAttribute("android:dependency", dependencyKey) } this.adoptChild("intent") { - setAttribute("android:targetPackage", targetPackage) + setAttribute("android:targetPackage", musicPackageName) setAttribute("android:data", key) setAttribute( "android:targetClass", diff --git a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockPatch.kt index 59ad7747c..9d1292d89 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockPatch.kt @@ -73,7 +73,7 @@ object SponsorBlockPatch : ResourcePatch() { context["res/xml/sponsorblock_prefs.xml"].readText() .replace( "\"com.google.android.apps.youtube.music\"", - "\"" + ResourceUtils.targetPackage + "\"" + "\"" + ResourceUtils.musicPackageName + "\"" ) ) diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt new file mode 100644 index 000000000..422de4e98 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt @@ -0,0 +1,341 @@ +package app.revanced.patches.shared.gms + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +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.shared.gms.fingerprints.* +import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME +import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch.Constants.ACTIONS +import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES +import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS +import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_PATH +import app.revanced.patches.shared.packagename.PackageNamePatch +import app.revanced.util.exception +import app.revanced.util.getReference +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.OneRegisterInstruction +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 patched 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 mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method. + * @param integrationsPatchDependency The patch responsible for the integrations. + * @param gmsCoreSupportResourcePatch 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. + */ +abstract class BaseGmsCoreSupportPatch( + private val fromPackageName: String, + private val mainActivityOnCreateFingerprint: MethodFingerprint, + private val integrationsPatchDependency: PatchClass, + gmsCoreSupportResourcePatch: BaseGmsCoreSupportResourcePatch, + dependencies: Set = setOf(), + compatiblePackages: Set? = null, +) : BytecodePatch( + name = "GmsCore support", + description = "Allows patched Google apps to run without root and under a different package name " + + "by using GmsCore instead of Google Play Services.", + dependencies = setOf( + PackageNamePatch::class, + gmsCoreSupportResourcePatch::class, + integrationsPatchDependency, + ) + dependencies, + compatiblePackages = compatiblePackages, + fingerprints = setOf( + CastContextFetchFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + GmsCoreSupportFingerprint, + GooglePlayUtilityFingerprint, + PrimeMethodFingerprint, + ServiceCheckFingerprint, + mainActivityOnCreateFingerprint + ), + requiresIntegrations = true, +) { + private val gmsCoreVendorGroupId = "app.revanced" + + override fun execute(context: BytecodeContext) { + val packageName = PackageNamePatch.getPackageName(fromPackageName) + + // 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. + listOf( + CastContextFetchFingerprint, + CastDynamiteModuleFingerprint, + CastDynamiteModuleV2Fingerprint, + GooglePlayUtilityFingerprint, + ServiceCheckFingerprint + ).returnEarly() + + // Verify GmsCore is installed and whitelisted for power optimizations and background usage. + mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions( + 1, // Hack to not disturb other patches (such as the YTMusic integrations patch). + "invoke-static/range { p0 .. p0 }, $INTEGRATIONS_PATH/patches/GmsCoreSupport;->" + + "checkGmsCore(Landroid/content/Context;)V", + ) ?: throw mainActivityOnCreateFingerprint.exception + + // Change the vendor of GmsCore in ReVanced Integrations. + GmsCoreSupportFingerprint.result?.mutableClass?.methods + ?.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME } + ?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"") + ?: 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", gmsCoreVendorGroupId) + + // No vendor prefix for whatever reason... + "subscribedfeeds" -> "$gmsCoreVendorGroupId.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", gmsCoreVendorGroupId)}", + ) + } + } + + // gms also has a 'subscribedfeeds' authority, check for that one too + val subFeedsUriPrefix = "content://subscribedfeeds" + if (str.startsWith(subFeedsUriPrefix)) { + return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.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.getReference()?.string != fromPackageName) return@indexOfFirst false + + register = (it as OneRegisterInstruction).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", + + // gass + "com.google.android.gms.gass.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.tapandpay.service.BIND", + "com.google.android.gms.measurement.START", + "com.google.android.gms.languageprofile.service.START", + "com.google.android.gms.clearcut.service.START", + "com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE", + + // potoken + "com.google.android.gms.potokens.service.START", + + // droidguard/ safetynet + "com.google.android.gms.droidguard.service.START", + "com.google.android.gms.safetynet.service.START", + ) + + /** + * 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 +} diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..7390b6195 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportResourcePatch.kt @@ -0,0 +1,103 @@ +package app.revanced.patches.shared.gms + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patches.shared.packagename.PackageNamePatch +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 spoofedPackageSignature The signature of the package to spoof to. + * @param dependencies Additional dependencies of this patch. + */ +@Suppress("DEPRECATION") +abstract class BaseGmsCoreSupportResourcePatch( + private val fromPackageName: String, + private val spoofedPackageSignature: String, + dependencies: Set = setOf(), +) : ResourcePatch( + dependencies = setOf(PackageNamePatch::class) + dependencies +) { + private val gmsCoreVendorGroupId = "app.revanced" + + override fun execute(context: ResourceContext) { + 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 { editor -> + val document = editor.file + + val applicationNode = + document + .getElementsByTagName("application") + .item(0) + + // Spoof package name and signature. + applicationNode.adoptChild("meta-data") { + setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME") + setAttribute("android:value", fromPackageName) + } + + applicationNode.adoptChild("meta-data") { + setAttribute("android:name", "$gmsCoreVendorGroupId.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", "$gmsCoreVendorGroupId.android.gms") + } + } + } + + /** + * Patch the manifest to support GmsCore. + */ + private fun ResourceContext.patchManifest() { + val packageName = PackageNamePatch.getPackageName(fromPackageName) + + 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", + "$gmsCoreVendorGroupId.android.c2dm", + ).replace( + "", + "", + ), + ) + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastContextFetchFingerprint.kt similarity index 73% rename from src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastContextFetchFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastContextFetchFingerprint.kt index 9bd6b7f27..2cc78aac7 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastContextFetchFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastContextFetchFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt similarity index 77% rename from src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt index 72aeaa325..e05f9781b 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt similarity index 74% rename from src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt index b5c026734..1d9df0f83 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CastDynamiteModuleV2Fingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsCoreSupportFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsCoreSupportFingerprint.kt new file mode 100644 index 000000000..4f590c1a3 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GmsCoreSupportFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.shared.gms.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object GmsCoreSupportFingerprint : MethodFingerprint( + customFingerprint = { _, classDef -> + classDef.type.endsWith("GmsCoreSupport;") + }, +) { + const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId" +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GooglePlayUtilityFingerprint.kt similarity index 75% rename from src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GooglePlayUtilityFingerprint.kt index 6ac32f97c..635519b36 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/GooglePlayUtilityFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint @@ -10,7 +10,6 @@ object GooglePlayUtilityFingerprint : MethodFingerprint( parameters = listOf("L", "I"), strings = listOf( "This should never happen.", - "MetadataValueReader", - "com.google.android.gms" + "MetadataValueReader" ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt similarity index 56% rename from src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/PrimeFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt index 6d21fd872..10c98bc35 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/PrimeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/PrimeMethodFingerprint.kt @@ -1,7 +1,7 @@ -package app.revanced.patches.music.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -object PrimeFingerprint : MethodFingerprint( +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/utils/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/ServiceCheckFingerprint.kt similarity index 86% rename from src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/ServiceCheckFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/ServiceCheckFingerprint.kt index aa73e7ef5..6bad6f3b1 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/microg/fingerprints/ServiceCheckFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/ServiceCheckFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.utils.microg.fingerprints +package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/shared/microg/Constants.kt b/src/main/kotlin/app/revanced/patches/shared/microg/Constants.kt deleted file mode 100644 index 6900e795a..000000000 --- a/src/main/kotlin/app/revanced/patches/shared/microg/Constants.kt +++ /dev/null @@ -1,136 +0,0 @@ -package app.revanced.patches.shared.microg - -/** - * constants for microG builds with signature spoofing - */ -object Constants { - /** - * microG vendor name - * aka. package prefix / package base - */ - const val MICROG_VENDOR = "com.mgoogle" - - /** - * microG package name - */ - const val MICROG_PACKAGE_NAME = "$MICROG_VENDOR.android.gms" - - /** - * meta-data for microG package name spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_NAME = "$MICROG_PACKAGE_NAME.SPOOFED_PACKAGE_NAME" - - /** - * meta-data for microG package signature spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_SIGNATURE = - "$MICROG_PACKAGE_NAME.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/patches/shared/microg/MicroGBytecodeHelper.kt b/src/main/kotlin/app/revanced/patches/shared/microg/MicroGBytecodeHelper.kt deleted file mode 100644 index 8700e9089..000000000 --- a/src/main/kotlin/app/revanced/patches/shared/microg/MicroGBytecodeHelper.kt +++ /dev/null @@ -1,241 +0,0 @@ -package app.revanced.patches.shared.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -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.patches.shared.microg.Constants.ACTIONS -import app.revanced.patches.shared.microg.Constants.AUTHORITIES -import app.revanced.patches.shared.microg.Constants.MICROG_VENDOR -import app.revanced.patches.shared.microg.Constants.PERMISSIONS -import app.revanced.util.exception -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. - */ -object MicroGBytecodeHelper { - - /** - * 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() { - primeMethodFingerprint.result?.let { - var targetRegister = 2 - - it.mutableMethod.apply { - val targetIndex = implementation!!.instructions.indexOfFirst { instructions -> - if (instructions.opcode != Opcode.CONST_STRING) return@indexOfFirst false - - val instructionString = - ((instructions as Instruction21c).reference as StringReference).string - if (instructionString != fromPackageName) return@indexOfFirst false - - targetRegister = instructions.registerA - return@indexOfFirst true - } - - replaceInstruction( - targetIndex, - "const-string v$targetRegister, \"$toPackageName\"" - ) - } - } ?: throw primeMethodFingerprint.exception - } - } - - /** - * 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 - ) - ) - ) - } - } - } - } - } - - /** - * Return the resolved methods of a list of [MethodFingerprint] early. - */ - private fun List.returnEarly() { - this.forEach { fingerprint -> - fingerprint.result?.let { - it.mutableMethod.apply { - val stringInstructions = when (it.method.returnType.first()) { - 'L' -> """ - const/4 v0, 0x0 - return-object v0 - """ - - 'V' -> "return-void" - 'I' -> """ - const/4 v0, 0x0 - return v0 - """ - - else -> throw Exception("This case should never happen.") - } - addInstructions( - 0, stringInstructions - ) - } - } ?: throw fingerprint.exception - } - } -} diff --git a/src/main/kotlin/app/revanced/patches/shared/microg/MicroGManifestHelper.kt b/src/main/kotlin/app/revanced/patches/shared/microg/MicroGManifestHelper.kt deleted file mode 100644 index 513253507..000000000 --- a/src/main/kotlin/app/revanced/patches/shared/microg/MicroGManifestHelper.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.shared.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patches.shared.microg.Constants.META_GMS_PACKAGE_NAME -import app.revanced.patches.shared.microg.Constants.META_SPOOFED_PACKAGE_NAME -import app.revanced.patches.shared.microg.Constants.META_SPOOFED_PACKAGE_SIGNATURE -import app.revanced.patches.shared.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 - */ -@Suppress("DEPRECATION") -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 spoofedPackage The package to spoof. - * @param spoofedSignature The signature to spoof. - */ - fun ResourceContext.addSpoofingMetadata( - spoofedPackage: String, - spoofedSignature: String - ) { - this.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/patches/shared/microg/MicroGResourceHelper.kt b/src/main/kotlin/app/revanced/patches/shared/microg/MicroGResourceHelper.kt deleted file mode 100644 index f6213742b..000000000 --- a/src/main/kotlin/app/revanced/patches/shared/microg/MicroGResourceHelper.kt +++ /dev/null @@ -1,66 +0,0 @@ -package app.revanced.patches.shared.microg - -import app.revanced.patcher.data.ResourceContext - -/** - * Helper class for applying resource patches needed for the microg-support patches. - */ -@Suppress("DEPRECATION") -object MicroGResourceHelper { - /** - * Patch the manifest to work with MicroG. - * - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - */ - fun ResourceContext.patchManifest( - fromPackageName: String, - toPackageName: String - ) { - val manifest = this["AndroidManifest.xml"] - - manifest.writeText( - manifest.readText() - .replace( - "package=\"$fromPackageName", - "package=\"$toPackageName" - ).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( - "", - "" - ) - ) - } - - /** - * Patch the settings fragment to work with MicroG. - * - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - */ - fun ResourceContext.patchSetting( - fromPackageName: String, - toPackageName: String - ) { - val prefs = this["res/xml/settings_fragment.xml"] - - prefs.writeText( - prefs.readText() - .replace( - "android:targetPackage=\"$fromPackageName", - "android:targetPackage=\"$toPackageName" - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/packagename/PackageNamePatch.kt b/src/main/kotlin/app/revanced/patches/shared/packagename/PackageNamePatch.kt index 0094e212b..75c347cff 100644 --- a/src/main/kotlin/app/revanced/patches/shared/packagename/PackageNamePatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/packagename/PackageNamePatch.kt @@ -1,6 +1,7 @@ package app.revanced.patches.shared.packagename import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch @@ -18,11 +19,16 @@ import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatc object PackageNamePatch : ResourcePatch() { private const val CLONE_PACKAGE_NAME_YOUTUBE = "com.rvx.android.youtube" private const val DEFAULT_PACKAGE_NAME_YOUTUBE = "app.rvx.android.youtube" + internal const val ORIGINAL_PACKAGE_NAME_YOUTUBE = "com.google.android.youtube" private const val CLONE_PACKAGE_NAME_YOUTUBE_MUSIC = "com.rvx.android.apps.youtube.music" private const val DEFAULT_PACKAGE_NAME_YOUTUBE_MUSIC = "app.rvx.android.apps.youtube.music" + internal const val ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC = "com.google.android.apps.youtube.music" - internal val PackageNameYouTube by stringPatchOption( + internal var packageNameYouTube = DEFAULT_PACKAGE_NAME_YOUTUBE + internal var packageNameYouTubeMusic = DEFAULT_PACKAGE_NAME_YOUTUBE_MUSIC + + private val PackageNameYouTube by stringPatchOption( key = "PackageNameYouTube", default = DEFAULT_PACKAGE_NAME_YOUTUBE, values = mapOf( @@ -34,7 +40,7 @@ object PackageNamePatch : ResourcePatch() { required = true ) - internal val PackageNameYouTubeMusic by stringPatchOption( + private val PackageNameYouTubeMusic by stringPatchOption( key = "PackageNameYouTubeMusic", default = DEFAULT_PACKAGE_NAME_YOUTUBE_MUSIC, values = mapOf( @@ -47,5 +53,20 @@ object PackageNamePatch : ResourcePatch() { ) override fun execute(context: ResourceContext) { + if (PackageNameYouTube != null && PackageNameYouTube!! != ORIGINAL_PACKAGE_NAME_YOUTUBE) { + packageNameYouTube = PackageNameYouTube!! + } + if (PackageNameYouTubeMusic != null && PackageNameYouTubeMusic!! != ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC) { + packageNameYouTubeMusic = PackageNameYouTubeMusic!! + } + } + + fun getPackageName(originalPackageName: String): String { + if (originalPackageName == ORIGINAL_PACKAGE_NAME_YOUTUBE) { + return packageNameYouTube + } else if (originalPackageName == ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC) { + return packageNameYouTubeMusic + } + throw PatchException("Unknown package name!") } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/OverlayButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/OverlayButtonsPatch.kt index 96329e323..c1e21d41b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/OverlayButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/overlaybutton/general/OverlayButtonsPatch.kt @@ -11,7 +11,6 @@ import app.revanced.patches.youtube.overlaybutton.download.pip.DisablePiPPatch import app.revanced.patches.youtube.overlaybutton.fullscreen.FullscreenButtonPatch import app.revanced.patches.youtube.utils.integrations.Constants.OVERLAY_BUTTONS_PATH import app.revanced.patches.youtube.utils.overridespeed.OverrideSpeedHookPatch -import app.revanced.patches.youtube.utils.playerbutton.PlayerButtonHookPatch import app.revanced.patches.youtube.utils.playercontrols.PlayerControlsPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch @@ -31,7 +30,6 @@ import org.w3c.dom.Element DownloadButtonHookPatch::class, FullscreenButtonPatch::class, OverrideSpeedHookPatch::class, - PlayerButtonHookPatch::class, PlayerControlsPatch::class, SettingsPatch::class, SharedResourceIdPatch::class, diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt index 13280fb0b..249474460 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt @@ -66,8 +66,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "19.02.39" ] ) - ] + ], + use = false ) +@Suppress("unused") object SpoofPlayerParameterPatch : BytecodePatch( setOf( ParamsMapPutFingerprint, diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportPatch.kt new file mode 100644 index 000000000..5c4ab3526 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportPatch.kt @@ -0,0 +1,47 @@ +package app.revanced.patches.youtube.utils.gms + +import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch +import app.revanced.patches.shared.packagename.PackageNamePatch +import app.revanced.patches.shared.packagename.PackageNamePatch.ORIGINAL_PACKAGE_NAME_YOUTUBE +import app.revanced.patches.youtube.utils.fix.clientspoof.ClientSpoofPatch +import app.revanced.patches.youtube.utils.integrations.IntegrationsPatch +import app.revanced.patches.youtube.utils.mainactivity.fingerprints.MainActivityFingerprint +import app.revanced.patches.youtube.utils.settings.SettingsPatch + +@Suppress("unused") +object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( + fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE, + mainActivityOnCreateFingerprint = MainActivityFingerprint, + integrationsPatchDependency = IntegrationsPatch::class, + dependencies = setOf(ClientSpoofPatch::class, PackageNamePatch::class, SettingsPatch::class), + gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, + compatiblePackages = setOf( + CompatiblePackage( + "com.google.android.youtube", + setOf( + "18.29.38", + "18.30.37", + "18.31.40", + "18.32.39", + "18.33.40", + "18.34.38", + "18.35.36", + "18.36.39", + "18.37.36", + "18.38.44", + "18.39.41", + "18.40.34", + "18.41.39", + "18.42.41", + "18.43.45", + "18.44.41", + "18.45.43", + "18.46.45", + "18.48.39", + "18.49.37", + "19.01.34", + "19.02.39" + ), + ), + ) +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportResourcePatch.kt new file mode 100644 index 000000000..f5ea225f5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/gms/GmsCoreSupportResourcePatch.kt @@ -0,0 +1,33 @@ +package app.revanced.patches.youtube.utils.gms + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch +import app.revanced.patches.shared.packagename.PackageNamePatch +import app.revanced.patches.shared.packagename.PackageNamePatch.ORIGINAL_PACKAGE_NAME_YOUTUBE +import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePackageName +import app.revanced.patches.youtube.utils.settings.SettingsPatch + +object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch( + fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE, + spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a600", + dependencies = setOf(PackageNamePatch::class, SettingsPatch::class), +) { + override fun execute(context: ResourceContext) { + super.execute(context) + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: GMS_CORE_SETTINGS" + ) + ) + SettingsPatch.updatePatchStatus("GmsCore support") + + context.updatePackageName( + ORIGINAL_PACKAGE_NAME_YOUTUBE, + PackageNamePatch.packageNameYouTube + ) + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/Constants.kt deleted file mode 100644 index eeeed1823..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/Constants.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.utils.microg - -object Constants { - internal const val PACKAGE_NAME = "com.google.android.youtube" - internal const val SPOOFED_PACKAGE_NAME = PACKAGE_NAME - internal const val SPOOFED_PACKAGE_SIGNATURE = "24bb24c05e47e0aefa68a58a766179d9b613a600" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGBytecodePatch.kt deleted file mode 100644 index 56572f8e2..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGBytecodePatch.kt +++ /dev/null @@ -1,75 +0,0 @@ -package app.revanced.patches.youtube.utils.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.shared.microg.MicroGBytecodeHelper -import app.revanced.patches.shared.packagename.PackageNamePatch -import app.revanced.patches.youtube.utils.fix.clientspoof.ClientSpoofPatch -import app.revanced.patches.youtube.utils.fix.parameter.SpoofPlayerParameterPatch -import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH -import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch -import app.revanced.patches.youtube.utils.microg.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.utils.microg.fingerprints.CastContextFetchFingerprint -import app.revanced.patches.youtube.utils.microg.fingerprints.CastDynamiteModuleFingerprint -import app.revanced.patches.youtube.utils.microg.fingerprints.CastDynamiteModuleV2Fingerprint -import app.revanced.patches.youtube.utils.microg.fingerprints.GooglePlayUtilityFingerprint -import app.revanced.patches.youtube.utils.microg.fingerprints.PrimeFingerprint -import app.revanced.patches.youtube.utils.microg.fingerprints.ServiceCheckFingerprint - -@Patch( - dependencies = [ - ClientSpoofPatch::class, - MainActivityResolvePatch::class, - PackageNamePatch::class, - SpoofPlayerParameterPatch::class - ] -) -object MicroGBytecodePatch : BytecodePatch( - setOf( - CastContextFetchFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - GooglePlayUtilityFingerprint, - PrimeFingerprint, - ServiceCheckFingerprint - ) -) { - private const val INTEGRATIONS_CLASS_DESCRIPTOR = - "$UTILS_PATH/MicroGPatch;" - - override fun execute(context: BytecodeContext) { - - val packageName = PackageNamePatch.PackageNameYouTube - ?: throw PatchException("Invalid package name.") - - if (packageName == PACKAGE_NAME) - throw PatchException("Original package name is not available as package name for MicroG build.") - - // 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 - ) - ) - - MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_CLASS_DESCRIPTOR, "checkAvailability") - - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGPatch.kt deleted file mode 100644 index 9d61192a0..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/MicroGPatch.kt +++ /dev/null @@ -1,97 +0,0 @@ -package app.revanced.patches.youtube.utils.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.shared.microg.MicroGManifestHelper.addSpoofingMetadata -import app.revanced.patches.shared.microg.MicroGResourceHelper.patchManifest -import app.revanced.patches.shared.microg.MicroGResourceHelper.patchSetting -import app.revanced.patches.shared.packagename.PackageNamePatch -import app.revanced.patches.youtube.utils.microg.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.utils.microg.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.youtube.utils.microg.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.patches.youtube.utils.settings.ResourceUtils.setMicroG -import app.revanced.patches.youtube.utils.settings.SettingsPatch - -@Patch( - name = "MicroG support", - description = "Allows ReVanced Extended to run without root and under a different package name with MicroG.", - dependencies = [ - MicroGBytecodePatch::class, - PackageNamePatch::class, - SettingsPatch::class - ], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", - [ - "18.29.38", - "18.30.37", - "18.31.40", - "18.32.39", - "18.33.40", - "18.34.38", - "18.35.36", - "18.36.39", - "18.37.36", - "18.38.44", - "18.39.41", - "18.40.34", - "18.41.39", - "18.42.41", - "18.43.45", - "18.44.41", - "18.45.43", - "18.46.45", - "18.48.39", - "18.49.37", - "19.01.34", - "19.02.39" - ] - ) - ] -) -@Suppress("unused") -object MicroGPatch : ResourcePatch() { - override fun execute(context: ResourceContext) { - - val packageName = PackageNamePatch.PackageNameYouTube - ?: throw PatchException("Invalid package name.") - - if (packageName == PACKAGE_NAME) - throw PatchException("Original package name is not available as package name for MicroG build.") - - /** - * Add settings - */ - SettingsPatch.addPreference( - arrayOf( - "PREFERENCE: MICROG_SETTINGS" - ) - ) - SettingsPatch.updatePatchStatus("MicroG support") - - // update settings fragment - context.patchSetting( - PACKAGE_NAME, - packageName - ) - - // update manifest - context.patchManifest( - PACKAGE_NAME, - packageName - ) - - // add metadata to manifest - context.addSpoofingMetadata( - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - - setMicroG(packageName) - - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastContextFetchFingerprint.kt deleted file mode 100644 index fe83f4cb9..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastContextFetchFingerprint.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -object CastContextFetchFingerprint : MethodFingerprint( - strings = listOf("Error fetching CastContext.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt deleted file mode 100644 index c58eb6679..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -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/youtube/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt deleted file mode 100644 index 467d5d32d..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -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/youtube/utils/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/PrimeFingerprint.kt deleted file mode 100644 index 801a22fe4..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/PrimeFingerprint.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -object PrimeFingerprint : 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/utils/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/ServiceCheckFingerprint.kt deleted file mode 100644 index 4bfd5d98f..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/microg/fingerprints/ServiceCheckFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.utils.microg.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -object ServiceCheckFingerprint : MethodFingerprint( - returnType = "V", - accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, - parameters = listOf("L", "I"), - strings = listOf( - "Google Play Services not available", - "GooglePlayServices not available due to error " - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt index 37d8ecd38..3cd685112 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt @@ -5,17 +5,30 @@ import app.revanced.util.doRecursively import app.revanced.util.insertNode import org.w3c.dom.Element -@Suppress("MemberVisibilityCanBePrivate") +@Suppress("DEPRECATION", "MemberVisibilityCanBePrivate") object ResourceUtils { const val TARGET_PREFERENCE_PATH = "res/xml/revanced_prefs.xml" const val YOUTUBE_SETTINGS_PATH = "res/xml/settings_fragment.xml" - var targetPackage = "com.google.android.youtube" + var youtubePackageName = "com.google.android.youtube" - fun setMicroG(newPackage: String) { - targetPackage = newPackage + fun ResourceContext.updatePackageName( + fromPackageName: String, + toPackageName: String + ) { + youtubePackageName = toPackageName + + val prefs = this["res/xml/settings_fragment.xml"] + + prefs.writeText( + prefs.readText() + .replace( + "android:targetPackage=\"$fromPackageName", + "android:targetPackage=\"$toPackageName" + ) + ) } fun ResourceContext.addEntryValues( @@ -107,7 +120,7 @@ object ResourceUtils { ownerDocument.createElement("intent").also { intentNode -> intentNode.setAttribute( "android:targetPackage", - targetPackage + youtubePackageName ) intentNode.setAttribute("android:data", key + "_intent") intentNode.setAttribute("android:targetClass", targetClass) diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 77b12a012..d8069f744 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -4,6 +4,7 @@ package app.revanced.util 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.replaceInstruction import app.revanced.patcher.fingerprint.MethodFingerprint @@ -309,3 +310,28 @@ fun BytecodeContext.updatePatchStatus( } } } + +/** + * Return the resolved methods of [MethodFingerprint]s early. + */ +fun List.returnEarly(bool: Boolean = false) { + val const = if (bool) "0x1" else "0x0" + this.forEach { fingerprint -> + fingerprint.result?.let { result -> + val stringInstructions = when (result.method.returnType.first()) { + 'L' -> """ + const/4 v0, $const + return-object v0 + """ + 'V' -> "return-void" + 'I', 'Z' -> """ + const/4 v0, $const + return v0 + """ + else -> throw Exception("This case should never happen.") + } + + result.mutableMethod.addInstructions(0, stringInstructions) + } ?: throw fingerprint.exception + } +} diff --git a/src/main/resources/music/settings/host/values/strings.xml b/src/main/resources/music/settings/host/values/strings.xml index 330fc11e3..f69ab5d9b 100644 --- a/src/main/resources/music/settings/host/values/strings.xml +++ b/src/main/resources/music/settings/host/values/strings.xml @@ -1,10 +1,12 @@ - Please install MicroG. - MicroG is not found. - MicroG does not run in the background. - Enable cloud messaging settings to receive notifications. - Open MicroG + GmsCore does not have permission to run in the background. + GmsCore is not whitelisted from battery optimization. + Action needed + Enable cloud messaging to receive notifications. + Open GmsCore + GmsCore is not installed. Install it. + "Follow the 'Don't kill my app' guide for GmsCore." Account Action Bar diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index 7a58f35f6..d19e4349d 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -1,10 +1,12 @@ - Please install MicroG. - MicroG is not found. - MicroG does not run in the background. - Enable cloud messaging settings to receive notifications. - Open MicroG + GmsCore does not have permission to run in the background. + GmsCore is not whitelisted from battery optimization. + Action needed + Enable cloud messaging to receive notifications. + Open GmsCore + GmsCore is not installed. Install it. + "Follow the 'Don't kill my app' guide for GmsCore." Ads Alternative thumbnails diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index a36f4401f..0b91803e5 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -353,10 +353,10 @@ - + @@ -527,7 +527,7 @@ - +