feat: Add Internal data documents provider patch (#3830)

Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
Tim Schneeberger
2024-12-09 18:46:31 +01:00
committed by GitHub
parent f4659a328e
commit cb22f652ed
6 changed files with 407 additions and 46 deletions

View File

@ -60,6 +60,10 @@ public final class app/revanced/patches/all/misc/directory/ChangeDataDirectoryLo
public static final fun getChangeDataDirectoryLocationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatchKt {
public static final fun getExportInternalDataDocumentsProviderPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/all/misc/hex/HexPatchKt {
public static final fun getHexPatch ()Lapp/revanced/patcher/patch/RawResourcePatch;
}

View File

@ -1,58 +1,19 @@
package app.revanced.patches.all.misc.directory
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
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
import app.revanced.patches.all.misc.directory.documentsprovider.exportInternalDataDocumentsProviderPatch
@Suppress("unused")
@Deprecated(
"Superseded by internalDataDocumentsProviderPatch",
ReplaceWith("internalDataDocumentsProviderPatch"),
)
val changeDataDirectoryLocationPatch = bytecodePatch(
name = "Change data directory location",
// name = "Change data directory location",
description = "Changes the data directory in the application from " +
"the app internal storage directory to /sdcard/android/data accessible by root-less devices." +
"Using this patch can cause unexpected issues with some apps.",
use = false,
) {
dependsOn(
transformInstructionsPatch(
filterMap = filter@{ _, _, instruction, instructionIndex ->
val reference = instruction.getReference<MethodReference>() ?: return@filter null
if (!MethodUtil.methodSignaturesMatch(reference, MethodCall.GetDir.reference)) {
return@filter null
}
return@filter instructionIndex
},
transform = { method, index ->
val getDirInstruction = method.getInstruction<Instruction35c>(index)
val contextRegister = getDirInstruction.registerC
val dataRegister = getDirInstruction.registerD
method.replaceInstruction(
index,
"invoke-virtual { v$contextRegister, v$dataRegister }, " +
"Landroid/content/Context;->getExternalFilesDir(Ljava/lang/String;)Ljava/io/File;",
)
},
),
)
}
private enum class MethodCall(
val reference: MethodReference,
) {
GetDir(
ImmutableMethodReference(
"Landroid/content/Context;",
"getDir",
listOf("Ljava/lang/String;", "I"),
"Ljava/io/File;",
),
),
dependsOn(exportInternalDataDocumentsProviderPatch)
}

View File

@ -0,0 +1,58 @@
package app.revanced.patches.all.misc.directory.documentsprovider
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.asSequence
import app.revanced.util.getNode
@Suppress("unused")
val exportInternalDataDocumentsProviderPatch = resourcePatch(
name = "Export internal data documents provider",
description = "Exports a documents provider that grants access to the internal data directory of this app " +
"to file managers and other apps that support the Storage Access Framework.",
use = false,
) {
dependsOn(
bytecodePatch {
extendWith("extensions/all/misc/directory/export-internal-data-documents-provider.rve")
},
)
execute {
val documentsProviderClass =
"app.revanced.extension.all.misc.directory.documentsprovider.InternalDataDocumentsProvider"
document("AndroidManifest.xml").use { document ->
// Check if the provider is already declared
if (document.getElementsByTagName("provider")
.asSequence()
.any { it.attributes.getNamedItem("android:name")?.nodeValue == documentsProviderClass }
) {
return@execute
}
val authority =
document.getNode("manifest").attributes.getNamedItem("package").let {
// Select a URI authority name that is unique to the current app
"${it.nodeValue}.$documentsProviderClass"
}
// Register the documents provider
with(document.getNode("application")) {
document.createElement("provider").apply {
setAttribute("android:name", documentsProviderClass)
setAttribute("android:authorities", authority)
setAttribute("android:exported", "true")
setAttribute("android:grantUriPermissions", "true")
setAttribute("android:permission", "android.permission.MANAGE_DOCUMENTS")
document.createElement("intent-filter").apply {
document.createElement("action").apply {
setAttribute("android:name", "android.content.action.DOCUMENTS_PROVIDER")
}.let(this::appendChild)
}.let(this::appendChild)
}.let(this::appendChild)
}
}
}
}