diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfebce7e69..cbd1883bdf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,33 +1,3 @@
-# [6.1.0](https://github.com/ReVanced/revanced-patches/compare/v6.0.1...v6.1.0) (2026-03-18)
-
-
-### Bug Fixes
-
-* **Export internal data documents provider:** Correct S_IFLNK constant and symlink detection mask ([#6819](https://github.com/ReVanced/revanced-patches/issues/6819)) ([252617b](https://github.com/ReVanced/revanced-patches/commit/252617b8dd3f24e1ff9a04ba1d91b43dc29bd757))
-* **YouTube - Custom branding:** Fix double icons and change default branding to ReVanced ([#6806](https://github.com/ReVanced/revanced-patches/issues/6806)) ([e51c529](https://github.com/ReVanced/revanced-patches/commit/e51c5292c171325e7cfa0f5ee85474d9b3961a34))
-
-
-### Features
-
-* Add `Spoof root of trust` and `Spoof keystore security level` patch ([#6751](https://github.com/ReVanced/revanced-patches/issues/6751)) ([4bc8c7c](https://github.com/ReVanced/revanced-patches/commit/4bc8c7c0f60a095533f07dc281f0320f8eb22f3c))
-* **Announcements:** Support ReVanced API v5 announcements ([a05386e](https://github.com/ReVanced/revanced-patches/commit/a05386e8bc24c085b5c74f3674c402c5dd5ad468))
-* Change contact email in patches about ([df1c3a4](https://github.com/ReVanced/revanced-patches/commit/df1c3a4a70fd2595d77b539299f1f7301bc60d24))
-* **Instagram:** Add `Enable location sticker redesign` patch ([#6808](https://github.com/ReVanced/revanced-patches/issues/6808)) ([4b699da](https://github.com/ReVanced/revanced-patches/commit/4b699da220e5d1527c390792b6228e2d9cffedb7))
-* **Spoof video streams:** Add Android Reel client to fix playback issues ([#6830](https://github.com/ReVanced/revanced-patches/issues/6830)) ([4b6c3e3](https://github.com/ReVanced/revanced-patches/commit/4b6c3e312328fbf6a1c7065e27d8ff04573e58be))
-
-# [6.1.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v6.1.0-dev.3...v6.1.0-dev.4) (2026-03-18)
-
-
-### Bug Fixes
-
-* **YouTube - Custom branding:** Fix double icons and change default branding to ReVanced ([#6806](https://github.com/ReVanced/revanced-patches/issues/6806)) ([e51c529](https://github.com/ReVanced/revanced-patches/commit/e51c5292c171325e7cfa0f5ee85474d9b3961a34))
-
-
-### Features
-
-* Add `Spoof root of trust` and `Spoof keystore security level` patch ([#6751](https://github.com/ReVanced/revanced-patches/issues/6751)) ([4bc8c7c](https://github.com/ReVanced/revanced-patches/commit/4bc8c7c0f60a095533f07dc281f0320f8eb22f3c))
-* **Instagram:** Add `Enable location sticker redesign` patch ([#6808](https://github.com/ReVanced/revanced-patches/issues/6808)) ([4b699da](https://github.com/ReVanced/revanced-patches/commit/4b699da220e5d1527c390792b6228e2d9cffedb7))
-
# [6.1.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v6.1.0-dev.2...v6.1.0-dev.3) (2026-03-18)
diff --git a/extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/play/DisablePlayIntegrityPatch.java b/extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/playintegrity/DisablePlayIntegrityPatch.java
similarity index 92%
rename from extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/play/DisablePlayIntegrityPatch.java
rename to extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/playintegrity/DisablePlayIntegrityPatch.java
index 4dd09f693f..a27e56be95 100644
--- a/extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/play/DisablePlayIntegrityPatch.java
+++ b/extensions/all/misc/disable-play-integrity/src/main/java/app/revanced/extension/playintegrity/DisablePlayIntegrityPatch.java
@@ -1,4 +1,4 @@
-package app.revanced.extension.play;
+package app.revanced.extension.playintegrity;
import android.content.Context;
import android.content.Intent;
diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/patches/CustomBrandingPatch.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/patches/CustomBrandingPatch.java
index d13513e2df..0dc411f8b0 100644
--- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/patches/CustomBrandingPatch.java
+++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/patches/CustomBrandingPatch.java
@@ -114,7 +114,7 @@ public class CustomBrandingPatch {
/**
* Injection point.
- *
+ *
* The total number of app name aliases, including dummy aliases.
*/
private static int numberOfPresetAppNames() {
@@ -146,13 +146,13 @@ public class CustomBrandingPatch {
public static int getDefaultAppNameIndex() {
return userProvidedCustomName()
? numberOfPresetAppNames()
- : 2;
+ : 1;
}
public static BrandingTheme getDefaultIconStyle() {
return userProvidedCustomIcon()
? BrandingTheme.CUSTOM
- : BrandingTheme.ROUNDED;
+ : BrandingTheme.ORIGINAL;
}
/**
diff --git a/gradle.properties b/gradle.properties
index d65f6857e0..1ec45a3285 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,4 +4,4 @@ org.gradle.parallel = true
android.useAndroidX = true
android.uniquePackageNames = false
kotlin.code.style = official
-version = 6.1.0
+version = 6.1.0-dev.3
diff --git a/patches/api/patches.api b/patches/api/patches.api
index 4a8ed81323..be251e84a5 100644
--- a/patches/api/patches.api
+++ b/patches/api/patches.api
@@ -89,14 +89,10 @@ public final class app/revanced/patches/all/misc/packagename/ChangePackageNamePa
public static final fun setOrGetFallbackPackageName (Ljava/lang/String;)Ljava/lang/String;
}
-public final class app/revanced/patches/all/misc/play/DisablePlayIntegrityKt {
+public final class app/revanced/patches/all/misc/playintegrity/DisablePlayIntegrityKt {
public static final fun getDisablePlayIntegrityPatch ()Lapp/revanced/patcher/patch/Patch;
}
-public final class app/revanced/patches/all/misc/play/SpoofPlayAgeSignalsKt {
- public static final fun getSpoofPlayAgeSignalsPatch ()Lapp/revanced/patcher/patch/Patch;
-}
-
public final class app/revanced/patches/all/misc/resources/AddResourcesPatchKt {
public static final fun addResource (Ljava/lang/String;Lapp/revanced/util/resource/BaseResource;)Z
public static final fun addResources (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;)Z
@@ -129,14 +125,6 @@ public final class app/revanced/patches/all/misc/spoof/EnableRomSignatureSpoofin
public static final fun getEnableROMSignatureSpoofingPatch ()Lapp/revanced/patcher/patch/Patch;
}
-public final class app/revanced/patches/all/misc/spoof/SpoofKeystoreSecurityLevelPatchKt {
- public static final fun getSpoofKeystoreSecurityLevelPatch ()Lapp/revanced/patcher/patch/Patch;
-}
-
-public final class app/revanced/patches/all/misc/spoof/SpoofRootOfTrustPatchKt {
- public static final fun getSpoofRootOfTrustPatch ()Lapp/revanced/patcher/patch/Patch;
-}
-
public final class app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34Kt {
public static final fun getSetTargetSDKVersion34Patch ()Lapp/revanced/patcher/patch/Patch;
}
@@ -377,10 +365,6 @@ public final class app/revanced/patches/instagram/story/flipping/DisableStoryAut
public static final fun getDisableStoryAutoFlippingPatch ()Lapp/revanced/patcher/patch/Patch;
}
-public final class app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatchKt {
- public static final fun getEnableLocationStickerRedesignPatch ()Lapp/revanced/patcher/patch/Patch;
-}
-
public final class app/revanced/patches/irplus/ad/RemoveAdsPatchKt {
public static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/Patch;
}
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatch.kt
index cb5723de76..a7dfdf7bf4 100644
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatch.kt
@@ -6,8 +6,7 @@ import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.intOption
import app.revanced.patcher.patch.stringOption
-import app.revanced.util.forEachInstructionAsSequence
-import com.android.tools.smali.dexlib2.iface.instruction.Instruction
+import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -34,8 +33,7 @@ val spoofSIMProviderPatch = bytecodePatch(
validator = { it: String? -> it == null || it.uppercase() in countries.values },
)
- fun isMccMncValid(it: Int?) = it == null || (it in 10000..999999)
- fun isNumericValid(it: String?, length: Int) = it.isNullOrBlank() || it.equals("random", true) || it.length == length
+ fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
val networkCountryIso by isoCountryPatchOption("Network ISO country code")
@@ -63,119 +61,46 @@ val spoofSIMProviderPatch = bytecodePatch(
description = "The full name of the SIM operator.",
)
- val imei by stringOption(
- name = "IMEI value",
- description = "15-digit IMEI to spoof, blank to skip, or 'random'.",
- validator = { isNumericValid(it, 15) },
- )
-
- val meid by stringOption(
- name = "MEID value",
- description = "14-char hex MEID to spoof, blank to skip, or 'random'.",
- validator = { isNumericValid(it, 14) },
- )
-
- val imsi by stringOption(
- name = "IMSI (Subscriber ID)",
- description = "15-digit IMSI to spoof, blank to skip, or 'random'.",
- validator = { isNumericValid(it, 15) },
- )
-
- val iccid by stringOption(
- name = "ICCID (SIM Serial)",
- description = "19-digit ICCID to spoof, blank to skip, or 'random'.",
- validator = { isNumericValid(it, 19) },
- )
-
- val phone by stringOption(
- name = "Phone number",
- description = "Phone number to spoof, blank to skip, or 'random'.",
- validator = { it.isNullOrBlank() || it.equals("random", ignoreCase = true) || it.startsWith("+") },
- )
-
dependsOn(
- bytecodePatch {
- apply {
- fun generateRandomNumeric(length: Int) = (1..length).map { ('0'..'9').random() }.joinToString("")
+ transformInstructionsPatch(
+ filterMap = { _, _, instruction, instructionIndex ->
+ if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null
- fun String?.computeSpoof(randomizer: () -> String): String? {
- if (this.isNullOrBlank()) return null
- if (this.equals("random", ignoreCase = true)) return randomizer()
- return this
+ val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null
+
+ val match = MethodCall.entries.firstOrNull { search ->
+ MethodUtil.methodSignaturesMatch(reference, search.reference)
+ } ?: return@transformInstructionsPatch null
+
+ val replacement = when (match) {
+ MethodCall.NetworkCountryIso -> networkCountryIso?.lowercase()
+ MethodCall.NetworkOperator -> networkOperator?.toString()
+ MethodCall.NetworkOperatorName -> networkOperatorName
+ MethodCall.SimCountryIso -> simCountryIso?.lowercase()
+ MethodCall.SimOperator -> simOperator?.toString()
+ MethodCall.SimOperatorName -> simOperatorName
}
-
- // Calculate the Luhn checksum (mod 10) to generate a valid 15th digit, standard for IMEI numbers.
- // Structure of an IMEI is as follows:
- // TAC (Type Allocation Code): First 8 digits (e.g., "86" + 6 digits)
- // SNR (Serial Number): Next 6 digits
- // CD (Check Digit): The 15th digit
- val computedImei = imei.computeSpoof {
- val prefix = "86" + generateRandomNumeric(12)
-
- val sum = prefix.mapIndexed { i, c ->
- var d = c.digitToInt()
- // Double every second digit (index 1, 3, 5...).
- if (i % 2 != 0) {
- d *= 2
- // If result is two digits (e.g. 14), sum them (1+4=5).
- // This is mathematically equivalent to d - 9.
- if (d > 9) d -= 9
- }
- d
- }.sum()
- // Append the calculated check digit to the 14-digit prefix.
- prefix + ((10 - (sum % 10)) % 10)
- }
-
- val computedMeid = meid.computeSpoof { (1..14).map { "0123456789ABCDEF".random() }.joinToString("") }?.uppercase()
- val computedImsi = imsi.computeSpoof { generateRandomNumeric(15) }
- val computedIccid = iccid.computeSpoof { "89" + generateRandomNumeric(17) }
- val computedPhone = phone.computeSpoof { "+" + generateRandomNumeric(11) }
-
- forEachInstructionAsSequence(
- match = { _, _, instruction, instructionIndex ->
- if (instruction !is ReferenceInstruction) return@forEachInstructionAsSequence null
-
- val reference = instruction.reference as? MethodReference ?: return@forEachInstructionAsSequence null
-
- val match = MethodCall.entries.firstOrNull { search ->
- MethodUtil.methodSignaturesMatch(reference, search.reference)
- } ?: return@forEachInstructionAsSequence null
-
- val replacement = when (match) {
- MethodCall.NetworkCountryIso -> networkCountryIso?.lowercase()
- MethodCall.NetworkOperator -> networkOperator?.toString()
- MethodCall.NetworkOperatorName -> networkOperatorName
- MethodCall.SimCountryIso -> simCountryIso?.lowercase()
- MethodCall.SimOperator -> simOperator?.toString()
- MethodCall.SimOperatorName -> simOperatorName
- MethodCall.Imei, MethodCall.ImeiWithSlot, MethodCall.DeviceId, MethodCall.DeviceIdWithSlot -> computedImei
- MethodCall.Meid, MethodCall.MeidWithSlot -> computedMeid
- MethodCall.SubscriberId, MethodCall.SubscriberIdWithSlot -> computedImsi
- MethodCall.SimSerialNumber, MethodCall.SimSerialNumberWithSlot -> computedIccid
- MethodCall.Line1Number, MethodCall.Line1NumberWithSlot -> computedPhone
- }
- replacement?.let { instructionIndex to it }
- },
- transform = ::transformMethodCall
- )
- }
- },
+ replacement?.let { instructionIndex to it }
+ },
+ transform = ::transformMethodCall,
+ ),
)
}
-private fun transformMethodCall(mutableMethod: MutableMethod, entry: Pair) {
- val (index, value) = entry
- val nextInstr = mutableMethod.getInstruction(index + 1)
+private fun transformMethodCall(
+ mutableMethod: MutableMethod,
+ entry: Pair,
+) {
+ val (instructionIndex, methodCallValue) = entry
- if (nextInstr.opcode.name != "move-result-object") {
- mutableMethod.replaceInstruction(index, "nop")
- return
- }
+ // Get the register which would have contained the return value
+ val register = mutableMethod.getInstruction(instructionIndex + 1).registerA
- val register = (nextInstr as OneRegisterInstruction).registerA
- mutableMethod.replaceInstruction(index, "const-string v$register, \"$value\"")
- mutableMethod.replaceInstruction(index + 1, "nop")
+ // Replace the move-result instruction with our fake value
+ mutableMethod.replaceInstruction(
+ instructionIndex + 1,
+ "const-string v$register, \"$methodCallValue\"",
+ )
}
private enum class MethodCall(
@@ -229,100 +154,4 @@ private enum class MethodCall(
"Ljava/lang/String;",
),
),
- Imei(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getImei",
- emptyList(),
- "Ljava/lang/String;"
- ),
- ),
- ImeiWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getImei",
- listOf("I"),
- "Ljava/lang/String;"
- ),
- ),
- DeviceId(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getDeviceId",
- emptyList(),
- "Ljava/lang/String;"
- ),
- ),
- DeviceIdWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getDeviceId",
- listOf("I"),
- "Ljava/lang/String;"
- ),
- ),
- Meid(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getMeid",
- emptyList(),
- "Ljava/lang/String;"
- ),
- ),
- MeidWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getMeid",
- listOf("I"),
- "Ljava/lang/String;"
- ),
- ),
- SubscriberId(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getSubscriberId",
- emptyList(),
- "Ljava/lang/String;"
- )
- ),
- SubscriberIdWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getSubscriberId",
- listOf("I"),
- "Ljava/lang/String;"
- )
- ),
- SimSerialNumber(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getSimSerialNumber",
- emptyList(),
- "Ljava/lang/String;"
- )
- ),
- SimSerialNumberWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getSimSerialNumber",
- listOf("I"),
- "Ljava/lang/String;"
- )
- ),
- Line1Number(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getLine1Number",
- emptyList(),
- "Ljava/lang/String;"
- )
- ),
- Line1NumberWithSlot(
- ImmutableMethodReference(
- "Landroid/telephony/TelephonyManager;",
- "getLine1Number",
- listOf("I"),
- "Ljava/lang/String;"
- )
- )
}
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatch.kt
index e00f37feaf..1666a27a8d 100644
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatch.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.all.misc.connectivity.wifi.spoof
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
-import app.revanced.util.forEachInstructionAsSequence
+import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/extension/all/misc/connectivity/wifi/spoof/SpoofWifiPatch"
@@ -19,32 +19,29 @@ val spoofWiFiConnectionPatch = bytecodePatch(
extendWith("extensions/all/misc/connectivity/wifi/spoof/spoof-wifi.rve")
dependsOn(
- bytecodePatch {
- apply {
- forEachInstructionAsSequence(
- match = { classDef, _, instruction, instructionIndex ->
- filterMapInstruction35c(
- EXTENSION_CLASS_DESCRIPTOR_PREFIX,
- classDef,
- instruction,
- instructionIndex,
- )
- },
- transform = { method, entry ->
- val (methodType, instruction, instructionIndex) = entry
- methodType.replaceInvokeVirtualWithExtension(
- EXTENSION_CLASS_DESCRIPTOR,
- method,
- instruction,
- instructionIndex,
- )
- })
- }
- },
+ transformInstructionsPatch(
+ filterMap = { classDef, _, instruction, instructionIndex ->
+ filterMapInstruction35c(
+ EXTENSION_CLASS_DESCRIPTOR_PREFIX,
+ classDef,
+ instruction,
+ instructionIndex,
+ )
+ },
+ transform = { method, entry ->
+ val (methodType, instruction, instructionIndex) = entry
+ methodType.replaceInvokeVirtualWithExtension(
+ EXTENSION_CLASS_DESCRIPTOR,
+ method,
+ instruction,
+ instructionIndex,
+ )
+ },
+ ),
)
}
-// Information about method calls we want to replace.
+// Information about method calls we want to replace
@Suppress("unused")
private enum class MethodCall(
override val definedClassName: String,
@@ -92,13 +89,13 @@ private enum class MethodCall(
"Landroid/net/NetworkInfo;",
"getState",
arrayOf(),
- $$"Landroid/net/NetworkInfo$State;",
+ "Landroid/net/NetworkInfo\$State;",
),
GetDetailedState(
"Landroid/net/NetworkInfo;",
"getDetailedState",
arrayOf(),
- $$"Landroid/net/NetworkInfo$DetailedState;",
+ "Landroid/net/NetworkInfo\$DetailedState;",
),
IsActiveNetworkMetered(
"Landroid/net/ConnectivityManager;",
@@ -135,7 +132,7 @@ private enum class MethodCall(
"registerBestMatchingNetworkCallback",
arrayOf(
"Landroid/net/NetworkRequest;",
- $$"Landroid/net/ConnectivityManager$NetworkCallback;",
+ "Landroid/net/ConnectivityManager\$NetworkCallback;",
"Landroid/os/Handler;",
),
"V",
@@ -143,19 +140,19 @@ private enum class MethodCall(
RegisterDefaultNetworkCallback1(
"Landroid/net/ConnectivityManager;",
"registerDefaultNetworkCallback",
- arrayOf($$"Landroid/net/ConnectivityManager$NetworkCallback;"),
+ arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V",
),
RegisterDefaultNetworkCallback2(
"Landroid/net/ConnectivityManager;",
"registerDefaultNetworkCallback",
- arrayOf($$"Landroid/net/ConnectivityManager$NetworkCallback;", "Landroid/os/Handler;"),
+ arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"),
"V",
),
RegisterNetworkCallback1(
"Landroid/net/ConnectivityManager;",
"registerNetworkCallback",
- arrayOf("Landroid/net/NetworkRequest;", $$"Landroid/net/ConnectivityManager$NetworkCallback;"),
+ arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V",
),
RegisterNetworkCallback2(
@@ -169,7 +166,7 @@ private enum class MethodCall(
"registerNetworkCallback",
arrayOf(
"Landroid/net/NetworkRequest;",
- $$"Landroid/net/ConnectivityManager$NetworkCallback;",
+ "Landroid/net/ConnectivityManager\$NetworkCallback;",
"Landroid/os/Handler;",
),
"V",
@@ -177,13 +174,13 @@ private enum class MethodCall(
RequestNetwork1(
"Landroid/net/ConnectivityManager;",
"requestNetwork",
- arrayOf("Landroid/net/NetworkRequest;", $$"Landroid/net/ConnectivityManager$NetworkCallback;"),
+ arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V",
),
RequestNetwork2(
"Landroid/net/ConnectivityManager;",
"requestNetwork",
- arrayOf("Landroid/net/NetworkRequest;", $$"Landroid/net/ConnectivityManager$NetworkCallback;", "I"),
+ arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "I"),
"V",
),
RequestNetwork3(
@@ -191,7 +188,7 @@ private enum class MethodCall(
"requestNetwork",
arrayOf(
"Landroid/net/NetworkRequest;",
- $$"Landroid/net/ConnectivityManager$NetworkCallback;",
+ "Landroid/net/ConnectivityManager\$NetworkCallback;",
"Landroid/os/Handler;",
),
"V",
@@ -207,7 +204,7 @@ private enum class MethodCall(
"requestNetwork",
arrayOf(
"Landroid/net/NetworkRequest;",
- $$"Landroid/net/ConnectivityManager$NetworkCallback;",
+ "Landroid/net/ConnectivityManager\$NetworkCallback;",
"Landroid/os/Handler;",
"I",
),
@@ -216,7 +213,7 @@ private enum class MethodCall(
UnregisterNetworkCallback1(
"Landroid/net/ConnectivityManager;",
"unregisterNetworkCallback",
- arrayOf($$"Landroid/net/ConnectivityManager$NetworkCallback;"),
+ arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V",
),
UnregisterNetworkCallback2(
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/play/SpoofPlayAgeSignals.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/play/SpoofPlayAgeSignals.kt
deleted file mode 100644
index ccb41b81b4..0000000000
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/play/SpoofPlayAgeSignals.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-package app.revanced.patches.all.misc.play
-
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.extensions.getInstruction
-import app.revanced.patcher.extensions.removeInstructions
-import app.revanced.patcher.patch.bytecodePatch
-import app.revanced.patcher.patch.intOption
-import app.revanced.patcher.patch.option
-import app.revanced.util.forEachInstructionAsSequence
-import app.revanced.util.getReference
-import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
-import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
-import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
-
-@Suppress("unused")
-val spoofPlayAgeSignalsPatch = bytecodePatch(
- name = "Spoof Play Age Signals",
- description = "Spoofs Google Play data about the user's age and verification status.",
- use = false,
-) {
- val lowerAgeBound by intOption(
- name = "Lower age bound",
- description = "A positive integer.",
- default = 18,
- validator = { it == null || it > 0 },
- )
-
- val upperAgeBound by intOption(
- name = "Upper age bound",
- description = "A positive integer. Must be greater than the lower age bound.",
- default = Int.MAX_VALUE,
- validator = { it == null || it > lowerAgeBound!! },
- )
-
- val userStatus by intOption(
- name = "User status",
- description = "An integer representing the user status.",
- default = UserStatus.VERIFIED.value,
- values = UserStatus.entries.associate { it.name to it.value },
- )
-
- apply {
- forEachInstructionAsSequence(match = { classDef, _, instruction, instructionIndex ->
- // Avoid patching the library itself.
- if (classDef.type.startsWith("Lcom/google/android/play/agesignals/")) return@forEachInstructionAsSequence null
-
- // Keep method calls only.
- val reference = instruction.getReference()
- ?: return@forEachInstructionAsSequence null
-
- val match = MethodCall.entries.firstOrNull {
- reference == it.reference
- } ?: return@forEachInstructionAsSequence null
-
- val replacement = when (match) {
- MethodCall.AgeLower -> lowerAgeBound!!
- MethodCall.AgeUpper -> upperAgeBound!!
- MethodCall.UserStatus -> userStatus!!
- }
-
- replacement.let { instructionIndex to it }
- }, transform = { method, entry ->
- val (instructionIndex, replacement) = entry
-
- // Get the register which would have contained the return value.
- val register = method.getInstruction(instructionIndex + 1).registerA
-
- // Replace the call instructions with the spoofed value.
- method.removeInstructions(instructionIndex, 2)
- method.addInstructions(
- instructionIndex,
- """
- const v$register, $replacement
- invoke-static { v$register }, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
- move-result-object v$register
- """.trimIndent(),
- )
- })
- }
-}
-
-/**
- * See [AgeSignalsResult](https://developer.android.com/google/play/age-signals/reference/com/google/android/play/agesignals/AgeSignalsResult).
- */
-private enum class MethodCall(
- val reference: MethodReference,
-) {
- AgeLower(
- ImmutableMethodReference(
- "Lcom/google/android/play/agesignals/AgeSignalsResult;",
- "ageLower",
- emptyList(),
- "Ljava/lang/Integer;",
- ),
- ),
- AgeUpper(
- ImmutableMethodReference(
- "Lcom/google/android/play/agesignals/AgeSignalsResult;",
- "ageUpper",
- emptyList(),
- "Ljava/lang/Integer;",
- ),
- ),
- UserStatus(
- ImmutableMethodReference(
- "Lcom/google/android/play/agesignals/AgeSignalsResult;",
- "userStatus",
- emptyList(),
- "Ljava/lang/Integer;",
- ),
- ),
-}
-
-/**
- * All possible user verification statuses.
- *
- * See [AgeSignalsVerificationStatus](https://developer.android.com/google/play/age-signals/reference/com/google/android/play/agesignals/model/AgeSignalsVerificationStatus).
- */
-private enum class UserStatus(val value: Int) {
- /** The user provided their age, but it hasn't been verified yet. */
- DECLARED(5),
-
- /** The user is 18+. */
- VERIFIED(0),
-
- /** The user's guardian has set the age for him. */
- SUPERVISED(1),
-
- /** The user's guardian hasn't approved the significant changes yet. */
- SUPERVISED_APPROVAL_PENDING(2),
-
- /** The user's guardian has denied approval for one or more pending significant changes. */
- SUPERVISED_APPROVAL_DENIED(3),
-
- /** The user is not verified or supervised. */
- UNKNOWN(4),
-}
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/play/DisablePlayIntegrity.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/playintegrity/DisablePlayIntegrity.kt
similarity index 95%
rename from patches/src/main/kotlin/app/revanced/patches/all/misc/play/DisablePlayIntegrity.kt
rename to patches/src/main/kotlin/app/revanced/patches/all/misc/playintegrity/DisablePlayIntegrity.kt
index dd5dad79e4..12461fc40a 100644
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/play/DisablePlayIntegrity.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/playintegrity/DisablePlayIntegrity.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.all.misc.play
+package app.revanced.patches.all.misc.playintegrity
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
@@ -9,7 +9,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
-private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/play/DisablePlayIntegrityPatch;"
+private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/playintegrity/DisablePlayIntegrityPatch;"
private val CONTEXT_BIND_SERVICE_METHOD_REFERENCE = ImmutableMethodReference(
"Landroid/content/Context;",
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofKeystoreSecurityLevelPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofKeystoreSecurityLevelPatch.kt
deleted file mode 100644
index b45cfb4e0d..0000000000
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofKeystoreSecurityLevelPatch.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package app.revanced.patches.all.misc.spoof
-
-import app.revanced.patcher.extensions.replaceInstructions
-import app.revanced.patcher.patch.bytecodePatch
-import app.revanced.util.forEachInstructionAsSequence
-
-@Suppress("unused")
-val spoofKeystoreSecurityLevelPatch = bytecodePatch(
- name = "Spoof keystore security level",
- description = "Forces apps to see Keymaster and Attestation security levels as 'StrongBox' (Level 2).",
- use = false
-) {
- apply {
- forEachInstructionAsSequence(
- match = { _, method, _, _ ->
- // Match methods by comparing the current method to a reference criteria.
- val name = method.name.lowercase()
- if (name.contains("securitylevel") && method.returnType == "I") method else null
- },
- transform = { mutableMethod, _ ->
- // Ensure the method has an implementation before replacing.
- if (mutableMethod.implementation?.instructions?.iterator()?.hasNext() == true) {
- mutableMethod.replaceInstructions(0, "const/4 v0, 0x2\nreturn v0")
- }
- }
- )
- }
-}
\ No newline at end of file
diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofRootOfTrustPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofRootOfTrustPatch.kt
deleted file mode 100644
index 6177b7e317..0000000000
--- a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/SpoofRootOfTrustPatch.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package app.revanced.patches.all.misc.spoof
-
-import app.revanced.patcher.extensions.replaceInstructions
-import app.revanced.patcher.patch.bytecodePatch
-import app.revanced.util.forEachInstructionAsSequence
-import com.android.tools.smali.dexlib2.iface.reference.MethodReference
-import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
-import com.android.tools.smali.dexlib2.util.MethodUtil
-
-@Suppress("unused")
-val spoofRootOfTrustPatch = bytecodePatch(
- name = "Spoof root of trust",
- description = "Spoofs device integrity states (Locked Bootloader, Verified OS) for apps that perform local certificate attestation.",
- use = false
-) {
- apply {
- forEachInstructionAsSequence(
- match = { _, method, _, _ ->
- MethodCall.entries.firstOrNull { MethodUtil.methodSignaturesMatch(method, it.reference) }
- },
- transform = { mutableMethod, methodCall ->
- if (mutableMethod.implementation?.instructions?.iterator()?.hasNext() == true) {
- mutableMethod.replaceInstructions(0, methodCall.replacementInstructions)
- }
- }
- )
- }
-}
-
-private enum class MethodCall(
- val reference: MethodReference,
- val replacementInstructions: String,
-) {
- IsDeviceLockedRootOfTrust(
- ImmutableMethodReference(
- "LRootOfTrust;",
- "isDeviceLocked",
- emptyList(),
- "Z"
- ),
- "const/4 v0, 0x1\nreturn v0",
- ),
- GetVerifiedBootStateRootOfTrust(
- ImmutableMethodReference(
- "LRootOfTrust;",
- "getVerifiedBootState",
- emptyList(),
- "I"
- ),
- "const/4 v0, 0x0\nreturn v0",
- ),
- IsDeviceLockedAttestation(
- ImmutableMethodReference(
- "LAttestation;",
- "isDeviceLocked",
- emptyList(),
- "Z"
- ),
- "const/4 v0, 0x1\nreturn v0",
- ),
- GetVerifiedBootStateAttestation(
- ImmutableMethodReference(
- "LAttestation;",
- "getVerifiedBootState",
- emptyList(),
- "I"
- ),
- "const/4 v0, 0x0\nreturn v0",
- ),
-}
\ No newline at end of file
diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt
deleted file mode 100644
index 443d60d155..0000000000
--- a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/EnableLocationStickerRedesignPatch.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package app.revanced.patches.instagram.story.locationsticker
-
-import app.revanced.patcher.patch.bytecodePatch
-import app.revanced.util.returnEarly
-
-@Suppress("unused")
-val enableLocationStickerRedesignPatch = bytecodePatch(
- name = "Enable location sticker redesign",
- description = "Unlocks the redesigned location sticker with additional style options.",
- use = false,
-) {
- compatibleWith("com.instagram.android")
-
- apply {
- // The gate method reads a MobileConfig boolean flag and returns it directly.
- // Returning early with true bypasses the flag check entirely,
- // enabling the redesigned sticker styles regardless of server configuration.
- locationStickerRedesignGateMethodMatch.method.returnEarly(true)
- }
-}
diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt
deleted file mode 100644
index 0972d692c9..0000000000
--- a/patches/src/main/kotlin/app/revanced/patches/instagram/story/locationsticker/Fingerprints.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.revanced.patches.instagram.story.locationsticker
-
-import app.revanced.patcher.composingFirstMethod
-import app.revanced.patcher.instructions
-import app.revanced.patcher.invoke
-import app.revanced.patcher.patch.BytecodePatchContext
-
-// MobileConfig boolean key that gates the redesigned location sticker styles.
-// The method containing this constant reads the flag and returns it directly,
-// making it the sole control point for the feature. The key is stable across
-// app updates as MobileConfig keys are server-assigned constants.
-private const val LOCATION_STICKER_REDESIGN_CONFIG_KEY = 0x8105a100041e0dL
-
-internal val BytecodePatchContext.locationStickerRedesignGateMethodMatch by composingFirstMethod {
- instructions(LOCATION_STICKER_REDESIGN_CONFIG_KEY())
-}
diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt
index 9a583e2c7a..35baad31cf 100644
--- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt
@@ -3,6 +3,7 @@ package app.revanced.patches.shared.layout.branding
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.getInstruction
+import app.revanced.patcher.firstImmutableClassDef
import app.revanced.patcher.patch.*
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
import app.revanced.patches.all.misc.resources.addResources
@@ -125,14 +126,14 @@ internal fun baseCustomBrandingPatch(
val getBuilderIndex = if (isYouTubeMusic) {
// YT Music the field is not a plain object type.
indexOfFirstInstructionOrThrow {
- getReference()?.type == $$"Landroid/app/Notification$Builder;"
+ getReference()?.type == "Landroid/app/Notification\$Builder;"
}
} else {
// Find the field name of the notification builder. Field is an Object type.
val builderCastIndex = indexOfFirstInstructionOrThrow {
val reference = getReference()
opcode == Opcode.CHECK_CAST &&
- reference?.type == $$"Landroid/app/Notification$Builder;"
+ reference?.type == "Landroid/app/Notification\$Builder;"
}
indexOfFirstInstructionReversedOrThrow(builderCastIndex) {
getReference()?.type == "Ljava/lang/Object;"
@@ -147,11 +148,11 @@ internal fun baseCustomBrandingPatch(
).forEach { index ->
addInstructionsAtControlFlowLabel(
index,
- $$"""
+ """
move-object/from16 v0, p0
- iget-object v0, v0, $$builderFieldName
- check-cast v0, Landroid/app/Notification$Builder;
- invoke-static { v0 }, $$EXTENSION_CLASS_DESCRIPTOR->setNotificationIcon(Landroid/app/Notification$Builder;)V
+ iget-object v0, v0, $builderFieldName
+ check-cast v0, Landroid/app/Notification${'$'}Builder;
+ invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setNotificationIcon(Landroid/app/Notification${'$'}Builder;)V
""",
)
}
@@ -161,37 +162,16 @@ internal fun baseCustomBrandingPatch(
)
afterDependents {
- val useCustomName = customName != null
- val useCustomIcon = customIcon != null
- val isRootInstall = setOrGetFallbackPackageName(originalAppPackageName) == originalAppPackageName
-
// Can only check if app is root installation by checking if change package name patch is in use.
// and can only do that in the afterDependents block here.
// The UI preferences cannot be selectively added here, because the settings afterDependents block
// may have already run and the settings are already wrote to file.
// Instead, show a warning if any patch option was used (A rooted device launcher ignores the manifest changes),
// and the non-functional in-app settings are removed on app startup by extension code.
- if (isRootInstall && (useCustomName || useCustomIcon)) {
- Logger.getLogger(this::class.java.name).warning(
- "Custom branding does not work with root installation. No changes applied."
- )
- }
-
- if (!isRootInstall || useCustomName) {
- document("AndroidManifest.xml").use { document ->
- val application = document.getElementsByTagName("application").item(0) as Element
- application.setAttribute(
- "android:label",
- if (useCustomName) {
- // Use custom name everywhere.
- customName
- } else {
- // The YT application name can appear in some places alongside the system
- // YouTube app, such as the settings app list and in the "open with" file picker.
- // Because the YouTube app cannot be completely uninstalled and only disabled,
- // use a custom name for this situation to disambiguate which app is which.
- "@string/revanced_custom_branding_name_entry_2"
- }
+ if (customName != null || customIcon != null) {
+ if (setOrGetFallbackPackageName(originalAppPackageName) == originalAppPackageName) {
+ Logger.getLogger(this::class.java.name).warning(
+ "Custom branding does not work with root installation. No changes applied.",
)
}
}
@@ -332,19 +312,16 @@ internal fun baseCustomBrandingPatch(
activityAliasNameWithIntents,
).childNodes
- // If user provides a custom icon, then change the application icon ('static' icon)
- // which shows as the push notification for some devices, in the app settings,
- // and as the icon for the apk before installing.
- // This icon cannot be dynamically selected and this change must only be done if the
- // user provides an icon otherwise there is no way to restore the original YouTube icon.
- if (useCustomIcon) {
- application.setAttribute(
- "android:icon",
- "@mipmap/revanced_launcher_custom"
- )
- }
+ // The YT application name can appear in some places alongside the system
+ // YouTube app, such as the settings app list and in the "open with" file picker.
+ // Because the YouTube app cannot be completely uninstalled and only disabled,
+ // use a custom name for this situation to disambiguate which app is which.
+ application.setAttribute(
+ "android:label",
+ "@string/revanced_custom_branding_name_entry_2",
+ )
- val enabledNameIndex = if (useCustomName) numberOfPresetAppNames else 2 // 1 indexing.
+ val enabledNameIndex = if (useCustomName) numberOfPresetAppNames else 1 // 1 indexing.
val enabledIconIndex = if (useCustomIcon) iconStyleNames.size else 0 // 0 indexing.
for (appNameIndex in 1..numberOfPresetAppNames) {
@@ -359,7 +336,7 @@ internal fun baseCustomBrandingPatch(
iconMipmapName = originalLauncherIconName,
appNameIndex = appNameIndex,
useCustomName = useCustomNameLabel,
- enabled = false,
+ enabled = (appNameIndex == 1),
intentFilters,
),
)