Enable relinquishing access to Android content directories

* doc/emacs/android.texi (Android Document Providers): Document
new command.

* java/org/gnu/emacs/EmacsService.java (relinquishUriRights):
New function.

* src/Makefile.in (SOME_MACHINE_OBJECTS): Add androidvfs.c.

* src/android.c (android_init_emacs_service): Link to new
function.

* src/android.h (struct android_emacs_service)
<relinquish_uri_rights>: New field.

* src/androidfns.c:

* src/androidvfs.c (android_saf_tree_name)
(android_saf_tree_opendir): Minor adjustments to commentary.
(Fandroid_relinquish_directory_access): New function.
(syms_of_androidvfs): Define new subr.
This commit is contained in:
Po Lu 2024-04-05 15:04:09 +08:00
parent 2637b642d4
commit aad63f935f
7 changed files with 82 additions and 11 deletions

View file

@ -299,8 +299,8 @@ on some proprietary versions of Android.
@cindex /content/storage directory, Android
Android 5.0 introduces a new sort of program, the ``document
provider'': these programs are small programs that provide access to
their own files outside both the asset manager and the Unix
provider'': these programs are small services that provide access to
their own files independently of the asset manager and the Unix
filesystem. Emacs supports accessing files and directories they
provide, placing their files within the directory
@file{/content/storage}.
@ -311,12 +311,15 @@ first request the right to access it. This is done by running the
command (@pxref{M-x}) @code{android-request-directory-access}, which
displays a file selection dialog.
If a directory is selected within this dialog, its contents are
If a directory is selected from this dialog, its contents are
subsequently made available within a new directory named
@file{/content/storage/@var{authority}/@var{id}}, where
@var{authority} is the name of the document provider, and @var{id} is
a unique identifier assigned to the directory by the document
provider.
@file{/content/storage/@var{authority}/@var{id}}, where @var{authority}
is the name of the document provider, and @var{id} is a unique
identifier assigned to the directory by the document provider.
@findex android-relinquish-directory-access
Such a directory can be deleted once no longer required by providing
its name to the command @code{android-relinquish-directory-access}.
The same limitations applied to the @file{/assets} directory
(@pxref{Android File System}) are applied when creating sub-processes

View file

@ -1973,6 +1973,21 @@ In addition, arbitrary runtime exceptions (such as
return false;
}
/* Relinquish authorization for read and write access to the provided
URI, which is generally a reference to a directory tree. */
public void
relinquishUriRights (String uri)
{
Uri uri1;
int flags;
uri1 = Uri.parse (uri);
flags = (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
resolver.releasePersistableUriPermission (uri1, flags);
}
/* Functions for detecting and requesting storage permissions. */

View file

@ -494,7 +494,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
xsettings.o xgselect.o termcap.o hbfont.o \
haikuterm.o haikufns.o haikumenu.o haikufont.o androidterm.o androidfns.o \
androidfont.o androidselect.c sfntfont-android.c sfntfont.c
androidfont.o androidselect.c androidvfs.c sfntfont-android.c sfntfont.c
## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
GMALLOC_OBJ=@GMALLOC_OBJ@

View file

@ -1690,6 +1690,8 @@ android_init_emacs_service (void)
"requestStorageAccess", "()V");
FIND_METHOD (cancel_notification,
"cancelNotification", "(Ljava/lang/String;)V");
FIND_METHOD (relinquish_uri_rights,
"relinquishUriRights", "(Ljava/lang/String;)V");
#undef FIND_METHOD
}

View file

@ -303,6 +303,7 @@ struct android_emacs_service
jmethodID external_storage_available;
jmethodID request_storage_access;
jmethodID cancel_notification;
jmethodID relinquish_uri_rights;
};
extern JNIEnv *android_java_env;

View file

@ -3146,7 +3146,7 @@ for more details about these values. */)
/* Directory access requests. */
/* SAF directory access management. */
DEFUN ("android-request-directory-access", Fandroid_request_directory_access,
Sandroid_request_directory_access, 0, 0, "",

View file

@ -4997,7 +4997,7 @@ android_saf_tree_name (struct android_vnode *vnode, char *name,
root.vnode.type = ANDROID_VNODE_SAF_ROOT;
root.vnode.flags = 0;
/* Find the authority from the URI. */
/* Derive the authority from the URI. */
fill = (char *) vp->tree_uri;
@ -5647,7 +5647,7 @@ android_saf_tree_opendir (struct android_vnode *vnode)
dir->vdir.closedir = android_saf_tree_closedir;
dir->vdir.dirfd = android_saf_tree_dirfd;
/* Find the authority from the URI. */
/* Derive the authority from the URI. */
fill = (char *) vp->tree_uri;
@ -7816,8 +7816,58 @@ android_closedir (struct android_vdir *dirp)
DEFUN ("android-relinquish-directory-access",
Fandroid_relinquish_directory_access,
Sandroid_relinquish_directory_access, 1, 1,
"DDirectory: ",
doc: /* Relinquish access to the provided directory.
DIRECTORY must be an inferior directory to a subdirectory of
/content/storage. Once the command completes, the parent of DIRECTORY
below that subdirectory from will cease to appear there, but no files
will be removed. */)
(Lisp_Object file)
{
struct android_vnode *vp;
struct android_saf_tree_vnode *saf_tree;
jstring string;
jmethodID method;
if (android_get_current_api_level () < 21)
error ("Emacs can only access or relinquish application storage on"
" Android 5.0 and later");
if (!android_init_gui)
return Qnil;
file = ENCODE_FILE (Fexpand_file_name (file, Qnil));
vp = android_name_file (SSDATA (file));
if (vp->type != ANDROID_VNODE_SAF_TREE)
{
(*vp->ops->close) (vp);
signal_error ("Access to this directory cannot be relinquished",
file);
}
saf_tree = (struct android_saf_tree_vnode *) vp;
string = android_build_jstring (saf_tree->tree_uri);
method = service_class.relinquish_uri_rights;
(*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
emacs_service,
service_class.class,
method, string);
(*vp->ops->close) (vp);
android_exception_check_1 (string);
ANDROID_DELETE_LOCAL_REF (string);
return Qnil;
}
void
syms_of_androidvfs (void)
{
DEFSYM (Qandroid_jni, "android-jni");
defsubr (&Sandroid_relinquish_directory_access);
}