diff options
| author | Po Lu | 2023-07-30 13:39:27 +0800 |
|---|---|---|
| committer | Po Lu | 2023-07-30 13:39:27 +0800 |
| commit | 37f68e8696200895832ee1f18b0cd1c0998bb207 (patch) | |
| tree | a473129dd3281c22c5696ce548326eb884496cc8 /java/org | |
| parent | 7ce7a004f68753beafb12830e28c459c4b5b6273 (diff) | |
| download | emacs-37f68e8696200895832ee1f18b0cd1c0998bb207.tar.gz emacs-37f68e8696200895832ee1f18b0cd1c0998bb207.zip | |
Partially implement rename operations on SAF files
* java/org/gnu/emacs/EmacsSafThread.java
(postInvalidateCacheDir):
* java/org/gnu/emacs/EmacsService.java (renameDocument): New
functions.
* src/android.c (android_init_emacs_service):
* src/android.h (struct android_emacs_service): Link to new JNI
function.
* src/androidvfs.c (android_saf_rename_document): New function.
(android_saf_tree_rename): Implement in terms of that function
if possible.
Diffstat (limited to 'java/org')
| -rw-r--r-- | java/org/gnu/emacs/EmacsSafThread.java | 78 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 37 |
2 files changed, 113 insertions, 2 deletions
diff --git a/java/org/gnu/emacs/EmacsSafThread.java b/java/org/gnu/emacs/EmacsSafThread.java index b0d014ffe94..007ea9acfbd 100644 --- a/java/org/gnu/emacs/EmacsSafThread.java +++ b/java/org/gnu/emacs/EmacsSafThread.java | |||
| @@ -134,7 +134,7 @@ public final class EmacsSafThread extends HandlerThread | |||
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | 136 | ||
| 137 | private final class CacheToplevel | 137 | private static final class CacheToplevel |
| 138 | { | 138 | { |
| 139 | /* Map between document names and children. */ | 139 | /* Map between document names and children. */ |
| 140 | HashMap<String, DocIdEntry> children; | 140 | HashMap<String, DocIdEntry> children; |
| @@ -232,7 +232,7 @@ public final class EmacsSafThread extends HandlerThread | |||
| 232 | } | 232 | } |
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| 235 | private final class CacheEntry | 235 | private static final class CacheEntry |
| 236 | { | 236 | { |
| 237 | /* The type of this document. */ | 237 | /* The type of this document. */ |
| 238 | String type; | 238 | String type; |
| @@ -545,6 +545,80 @@ public final class EmacsSafThread extends HandlerThread | |||
| 545 | }); | 545 | }); |
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | /* Invalidate the cache entry denoted by DOCUMENT_ID, within the | ||
| 549 | document tree URI. | ||
| 550 | Call this after deleting a document or directory. | ||
| 551 | |||
| 552 | At the same time, remove the child referring to DOCUMENTID from | ||
| 553 | within CACHENAME's cache entry if it exists. */ | ||
| 554 | |||
| 555 | public void | ||
| 556 | postInvalidateCacheDir (final Uri uri, final String documentId, | ||
| 557 | final String cacheName) | ||
| 558 | { | ||
| 559 | handler.post (new Runnable () { | ||
| 560 | @Override | ||
| 561 | public void | ||
| 562 | run () | ||
| 563 | { | ||
| 564 | CacheToplevel toplevel; | ||
| 565 | HashMap<String, DocIdEntry> children; | ||
| 566 | String[] components; | ||
| 567 | CacheEntry entry; | ||
| 568 | DocIdEntry idEntry; | ||
| 569 | Iterator<DocIdEntry> iter; | ||
| 570 | |||
| 571 | toplevel = getCache (uri); | ||
| 572 | toplevel.idCache.remove (documentId); | ||
| 573 | |||
| 574 | /* Now remove DOCUMENTID from CACHENAME's cache entry, if | ||
| 575 | any. */ | ||
| 576 | |||
| 577 | children = toplevel.children; | ||
| 578 | components = cacheName.split ("/"); | ||
| 579 | |||
| 580 | for (String component : components) | ||
| 581 | { | ||
| 582 | /* Java `split' removes trailing empty matches but not | ||
| 583 | leading or intermediary ones. */ | ||
| 584 | if (component.isEmpty ()) | ||
| 585 | continue; | ||
| 586 | |||
| 587 | /* Search for this component within the last level | ||
| 588 | of the cache. */ | ||
| 589 | |||
| 590 | idEntry = children.get (component); | ||
| 591 | |||
| 592 | if (idEntry == null) | ||
| 593 | /* Not cached, so return. */ | ||
| 594 | return; | ||
| 595 | |||
| 596 | entry = toplevel.idCache.get (idEntry.documentId); | ||
| 597 | |||
| 598 | if (entry == null) | ||
| 599 | /* Not cached, so return. */ | ||
| 600 | return; | ||
| 601 | |||
| 602 | /* Locate the next component within this | ||
| 603 | directory. */ | ||
| 604 | children = entry.children; | ||
| 605 | } | ||
| 606 | |||
| 607 | iter = children.values ().iterator (); | ||
| 608 | while (iter.hasNext ()) | ||
| 609 | { | ||
| 610 | idEntry = iter.next (); | ||
| 611 | |||
| 612 | if (idEntry.documentId.equals (documentId)) | ||
| 613 | { | ||
| 614 | iter.remove (); | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | } | ||
| 619 | }); | ||
| 620 | } | ||
| 621 | |||
| 548 | 622 | ||
| 549 | 623 | ||
| 550 | /* ``Prototypes'' for nested functions that are run within the SAF | 624 | /* ``Prototypes'' for nested functions that are run within the SAF |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 5186dec974a..07e585ad37c 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -1698,4 +1698,41 @@ public final class EmacsService extends Service | |||
| 1698 | 1698 | ||
| 1699 | return -1; | 1699 | return -1; |
| 1700 | } | 1700 | } |
| 1701 | |||
| 1702 | /* Rename the document designated by DOCID inside the directory tree | ||
| 1703 | identified by URI, which should be within the directory | ||
| 1704 | designated by DIR, to NAME. If the file can't be renamed because | ||
| 1705 | it doesn't support renaming, return -1, 0 otherwise. */ | ||
| 1706 | |||
| 1707 | public int | ||
| 1708 | renameDocument (String uri, String docId, String dir, String name) | ||
| 1709 | throws FileNotFoundException | ||
| 1710 | { | ||
| 1711 | Uri tree, uriObject; | ||
| 1712 | |||
| 1713 | tree = Uri.parse (uri); | ||
| 1714 | uriObject = DocumentsContract.buildDocumentUriUsingTree (tree, docId); | ||
| 1715 | |||
| 1716 | try | ||
| 1717 | { | ||
| 1718 | if (DocumentsContract.renameDocument (resolver, uriObject, | ||
| 1719 | name) | ||
| 1720 | != null) | ||
| 1721 | { | ||
| 1722 | /* Invalidate the cache. */ | ||
| 1723 | if (storageThread != null) | ||
| 1724 | storageThread.postInvalidateCacheDir (tree, docId, | ||
| 1725 | name); | ||
| 1726 | return 0; | ||
| 1727 | } | ||
| 1728 | } | ||
| 1729 | catch (UnsupportedOperationException e) | ||
| 1730 | { | ||
| 1731 | ;; | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | /* Handle unsupported operation exceptions specially, so | ||
| 1735 | `android_rename' can return ENXDEV. */ | ||
| 1736 | return -1; | ||
| 1737 | } | ||
| 1701 | }; | 1738 | }; |