Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
oSumAtrIX committed Aug 24, 2024
1 parent 6b80eb8 commit e36b41d
Show file tree
Hide file tree
Showing 16 changed files with 278 additions and 382 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package app.revanced.patches.all.privacy

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
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.all.privacy.fingerprints.*
import app.revanced.util.resultOrThrow
import java.util.logging.Logger

@Patch(
name = "Disable analytics and telemetry",
description = "Patches the app to disable analytics and telemetry services.",
use = false,
)
@Suppress("unused")
object DisableAnalyticsAndTelemetryPatch : BytecodePatch(
setOf(
InitializeAsyncStatsigClientFingerprint,
InitAnalyticsFingerprint,
InitAppsFlyerSDKFingerprint,
SetupComsCoreFingerprint,
CallSettingsSpiFingerprint,
DoConfigFetchFingerprint,
SendFingerprint,
InitializeSdkFingerprint,
BuildSegmentFingerprint,
InitSDKFingerprint,
InitAmplitudeFingerprint,
),
) {
private val logger = Logger.getLogger(this::class.java.name)

private val disableGoogleAnalytics by option("Google Analytics")
private val disableAmplitude by option("Amplitude")
private val disableStatsig by option("Statsig")
private val disableAppsFlyerSDK by option("Apps Flyer SDK")
private val disableAppsFlyerPlugin by option("Apps Flyer plugin")
private val disableComsCore by option("ComsCore")
private val disableCrashlytics by option("Crashlytics")
private val disableFirebaseTransport by option("Firebase Transport")
private val disableMoEngage by option("MoEngage")
private val disableSegment by option("Segment")

override fun execute(context: BytecodeContext) = mapOf(
disableAmplitude to {
InitAmplitudeFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-object p0",
)
},
disableStatsig to {
InitializeAsyncStatsigClientFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-void",
)
},
disableAppsFlyerSDK to {
InitAppsFlyerSDKFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-object p0",
)
},
disableAppsFlyerPlugin to {
InitSDKFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-void",
)
},
disableComsCore to {
SetupComsCoreFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-void",
)
},
// Neutralize the method sending data to the backend.
disableFirebaseTransport to {
SendFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"return-void",
)
},
// Empties the "context" argument to force an exception.
disableGoogleAnalytics to {
InitAnalyticsFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"const/4 p0, 0x0",
)
},
// Empties the writeKey parameter to abort initialization
disableSegment to {
BuildSegmentFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"const-string p2, \"\"",
)
},
// Neutralize the two methods responsible for requesting Crashlytics' configuration.
// which effectively disables the SDK.
disableCrashlytics to {
CallSettingsSpiFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"""
const/4 p1, 0x0
return-object p1
""",
)

DoConfigFetchFingerprint.resultOrThrow().mutableMethod.apply {
// Jumps to the end of the method to directly return an empty object.
addInstructionsWithLabels(
0,
"""
goto :return_unit
""",
ExternalLabel("return_unit", getInstruction(getInstructions().lastIndex - 2)),
)
}
},
disableMoEngage to {
InitializeSdkFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"""
const/4 v0, 0x0
return-object v0
""",
)
},
).forEach { (option, patch) ->
val isEnabled by option
if (!isEnabled!!) return@forEach

val message = try {
patch()

"Disabled ${option.title}"
} catch (exception: PatchException) {
"${option.title} was not found. Skipping."
}

logger.info(message)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package app.revanced.patches.all.privacy

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.util.asSequence
import app.revanced.util.getNode
import org.w3c.dom.Document
import org.w3c.dom.Element
import java.util.logging.Logger

@Patch(
name = "Disable analytics and telemetry through manifest",
description = "Patches the manifest to disable analytics and telemetry services.",
use = false,
)
@Suppress("unused")
object DisableAnalyticsAndTelemetryThroughManifestPatch : ResourcePatch() {
private val logger = Logger.getLogger(this::class.java.name)

private val disableFirebaseTelemetry by option("Firebase telemetry")
private val disableFacebookSdk by option("Facebook SDK")
private val disableGoogleAnalytics by option("Google Analytics")

override fun execute(context: ResourceContext) {
context.document["AndroidManifest.xml"].use { document ->
mapOf(
disableFirebaseTelemetry to {
document.addMetadata(
"firebase_analytics_collection_enabled" to "false",
"firebase_analytics_collection_deactivated" to "true",
"firebase_crashlytics_collection_enabled" to "false",
"firebase_performance_collection_enabled" to "false",
"firebase_performance_collection_deactivated" to "true",
"firebase_data_collection_default_enabled" to "false",
)
},
disableFacebookSdk to {
document.addMetadata(
"com.facebook.sdk.AutoLogAppEventsEnabled" to "false",
"com.facebook.sdk.AdvertiserIDCollectionEnabled" to "false",
"com.facebook.sdk.MonitorEnabled" to "false",
"com.facebook.sdk.AutoInitEnabled" to "false",
)
},
disableGoogleAnalytics to {
document.addMetadata(
"google_analytics_adid_collection_enabled" to "false",
"google_analytics_default_allow_ad_personalization_signals" to "false",
"google_analytics_automatic_screen_reporting_enabled" to "false",
"google_analytics_default_allow_ad_storage" to "false",
"google_analytics_default_allow_ad_user_data" to "false",
"google_analytics_default_allow_analytics_storage" to "false",
"google_analytics_sgtm_upload_enabled" to "false",
"google_analytics_deferred_deep_link_enabled" to "false",
)
},
).forEach { option, patch ->
val isEnabled by option
if (!isEnabled!!) return@forEach

val message = try {
patch()

"Disabled ${option.title}"
} catch (exception: PatchException) {
"${option.title} was not found. Skipping."
}

logger.info(message)
}
}
}

private const val META_DATA_TAG = "meta-data"
private const val NAME_ATTRIBUTE = "android:name"
private const val VALUE_ATTRIBUTE = "android:value"

private fun Document.addMetadata(vararg metaDataNodes: Pair<String, String>) =
metaDataNodes.forEach { (nodeName, nodeValue) ->
val applicationNode = getNode("application") as Element
applicationNode.getElementsByTagName(META_DATA_TAG)
.asSequence()
.first { it.attributes.getNamedItem(NAME_ATTRIBUTE).nodeValue == nodeName }
.attributes.getNamedItem(VALUE_ATTRIBUTE).nodeValue = nodeValue
}
}
12 changes: 12 additions & 0 deletions src/main/kotlin/app/revanced/patches/all/privacy/PatchExtension.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.revanced.patches.all.privacy

import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
import kotlin.properties.ReadOnlyProperty

internal fun Patch<*>.option(
title: String,
) = ReadOnlyProperty<Any?, PatchOption<Boolean?>> { _, property ->
booleanPatchOption(key = property.name, default = true, title = title, required = true)
}
Loading

0 comments on commit e36b41d

Please sign in to comment.