Expose a patched app's private data to file managers without root - #101
Merged
Conversation
A module -- or the user -- often needs to reach a patched app's private data, and only that app's own UID can. A patch can now inject a DocumentsProvider that runs inside the app and serves its data directory through the Storage Access Framework, so any file manager that speaks SAF can browse it with no root. It is off by default and clearly an expert option, since it widens what can reach the app's data. The provider is declared in the manifest as a per-package authority behind the MANAGE_DOCUMENTS permission -- the one the system Documents UI holds -- so only the system can bind it and access reaches other apps only through the user granting a document or tree. Its exported and grantUriPermissions attributes must be written as real booleans: the platform reads them with TypedArray.getBoolean, which returns the default for a string, so a boolean spelled "true" silently un-exports the provider. The vendored ManifestEditor could only add providers as string pairs; core is bumped to the version that emits provider attributes with their real types. The harder half is that the platform instantiates a manifest-declared provider from the app's own class loader, which holds only the original apk and its splits -- never the loader's in-memory dex, where the provider class lives -- so installContentProviders failed the class at startup. The class cannot simply be grafted onto the app loader's dex path: ART binds an in-memory dex to the class-loader context it was defined under, and defining the class a second time elsewhere is rejected. Instead a filtering loader is spliced in as the app loader's parent; standard delegation consults it on every lookup, but it answers with exactly one class -- the provider, loaded by the loader that already owns it -- and defers everything else, so the app's own classes still resolve from its own dexes unchanged. The choice is recorded in the patched app's config, like the added permissions, so a re-patch that recovers only the original apks keeps it. The CLI gains --documents-provider; the manager's advanced sheet gains a toggle, and the permission editor moves below it -- its chip list is the tallest control in the group, so it sits last rather than pushing the compact toggles down. Strings are translated across every shipped locale. Closes #65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A module -- or the user -- often needs to reach a patched app's private data, and only that app's own UID can. This adds an opt-in that injects a
DocumentsProviderrunning inside the app, serving its data directory through the Storage Access Framework, so any SAF file manager can browse it with no root. It is off by default and clearly an expert option, since it widens what can reach the app's data.The provider is declared per-package behind
MANAGE_DOCUMENTS, so only the system Documents UI can bind it and access reaches other apps only through a granted document or tree. Itsexported/grantUriPermissionsare written as real booleans -- a string"true"is read back as false and silently un-exports it -- which is why core is bumped to the ManifestEditor that emits typed attributes. Because the platform instantiates the provider from the app's own class loader, which never sees the loader's dex, a filtering loader is spliced in as its parent to resolve that one class and defer everything else.Recorded in the patch config so a re-patch keeps it. Closes #65.