aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorPo Lu2023-07-28 12:21:47 +0800
committerPo Lu2023-07-28 12:21:47 +0800
commit03cf3bbb5c38aa55abd6f7d4860025f7482fcfc3 (patch)
treea8d55088a6efed2cbe4b0bfad1c1bde61579b54e /java
parent7c0899586471d3649dfb468d2b8f7d6d9685fea1 (diff)
downloademacs-03cf3bbb5c38aa55abd6f7d4860025f7482fcfc3.tar.gz
emacs-03cf3bbb5c38aa55abd6f7d4860025f7482fcfc3.zip
Update Android port
* java/org/gnu/emacs/EmacsDirectoryEntry.java (EmacsDirectoryEntry): Make class final. * java/org/gnu/emacs/EmacsService.java (accessDocument) (openDocumentDirectory, openDocument, createDocument): Throw access and IO error exceptions instead of catching them. (createDirectory, deleteDocument): New functions. * src/android.c (android_init_emacs_service): Add new functions. * src/android.h (struct android_emacs_service): Likewise. * src/androidvfs.c (android_saf_exception_check): New function. Translate between Java exceptions and errno values. (android_saf_stat, android_saf_access, android_saf_delete_document) (struct android_saf_tree_vnode, android_document_id_from_name) (android_saf_tree_name, android_saf_tree_rmdir) (android_saf_tree_opendir_1, android_saf_tree_opendir) (android_saf_file_open, android_saf_file_unlink) (android_saf_new_open, android_saf_new_mkdir): Implement missing VFS operations and derive errno values from the type of any exceptions thrown. (android_vfs_init): Initialize exception classes. (android_mkdir, android_fstat): Remove trailing whitespace.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsDirectoryEntry.java2
-rw-r--r--java/org/gnu/emacs/EmacsService.java210
2 files changed, 119 insertions, 93 deletions
diff --git a/java/org/gnu/emacs/EmacsDirectoryEntry.java b/java/org/gnu/emacs/EmacsDirectoryEntry.java
index 9c10f2e8771..75c52e48002 100644
--- a/java/org/gnu/emacs/EmacsDirectoryEntry.java
+++ b/java/org/gnu/emacs/EmacsDirectoryEntry.java
@@ -22,7 +22,7 @@ package org.gnu.emacs;
22/* Structure holding a single ``directory entry'' from a document 22/* Structure holding a single ``directory entry'' from a document
23 provider. */ 23 provider. */
24 24
25public class EmacsDirectoryEntry 25public final class EmacsDirectoryEntry
26{ 26{
27 /* The type of this directory entry. 0 means a regular file and 1 27 /* The type of this directory entry. 0 means a regular file and 1
28 means a directory. */ 28 means a directory. */
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index bc62e050345..aa672994f12 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -1723,9 +1723,12 @@ public final class EmacsService extends Service
1723 not: 1723 not:
1724 1724
1725 -1, if the file does not exist. 1725 -1, if the file does not exist.
1726 -2, upon a security exception or if WRITABLE the file 1726 -2, if WRITABLE and the file is not writable.
1727 is not writable. 1727 -3, upon any other error.
1728 -3, upon any other error. */ 1728
1729 In addition, arbitrary runtime exceptions (such as
1730 SecurityException or UnsupportedOperationException) may be
1731 thrown. */
1729 1732
1730 public int 1733 public int
1731 accessDocument (String uri, String documentId, boolean writable) 1734 accessDocument (String uri, String documentId, boolean writable)
@@ -1754,24 +1757,8 @@ public final class EmacsService extends Service
1754 Document.COLUMN_MIME_TYPE, 1757 Document.COLUMN_MIME_TYPE,
1755 }; 1758 };
1756 1759
1757 try 1760 cursor = resolver.query (uriObject, projection, null,
1758 { 1761 null, null);
1759 cursor = resolver.query (uriObject, projection, null,
1760 null, null);
1761 }
1762 catch (SecurityException exception)
1763 {
1764 /* A SecurityException can be thrown if Emacs doesn't have
1765 access to uriObject. */
1766 return -2;
1767 }
1768 catch (UnsupportedOperationException exception)
1769 {
1770 exception.printStackTrace ();
1771
1772 /* Why is this? */
1773 return -3;
1774 }
1775 1762
1776 if (cursor == null || !cursor.moveToFirst ()) 1763 if (cursor == null || !cursor.moveToFirst ())
1777 return -1; 1764 return -1;
@@ -1816,13 +1803,10 @@ public final class EmacsService extends Service
1816 if (writable && (tem & Document.FLAG_SUPPORTS_WRITE) == 0) 1803 if (writable && (tem & Document.FLAG_SUPPORTS_WRITE) == 0)
1817 return -3; 1804 return -3;
1818 } 1805 }
1819 catch (Exception exception) 1806 finally
1820 { 1807 {
1821 /* Whether or not type errors cause exceptions to be signaled 1808 /* Close the cursor if an exception occurs. */
1822 is defined ``by the implementation of Cursor'', whatever 1809 cursor.close ();
1823 that means. */
1824 exception.printStackTrace ();
1825 return -3;
1826 } 1810 }
1827 1811
1828 return 0; 1812 return 0;
@@ -1832,7 +1816,11 @@ public final class EmacsService extends Service
1832 designated by the specified DOCUMENTID within the tree URI. 1816 designated by the specified DOCUMENTID within the tree URI.
1833 1817
1834 If DOCUMENTID is NULL, use the document ID within URI itself. 1818 If DOCUMENTID is NULL, use the document ID within URI itself.
1835 Value is NULL upon failure. */ 1819 Value is NULL upon failure.
1820
1821 In addition, arbitrary runtime exceptions (such as
1822 SecurityException or UnsupportedOperationException) may be
1823 thrown. */
1836 1824
1837 public Cursor 1825 public Cursor
1838 openDocumentDirectory (String uri, String documentId) 1826 openDocumentDirectory (String uri, String documentId)
@@ -1861,25 +1849,8 @@ public final class EmacsService extends Service
1861 Document.COLUMN_MIME_TYPE, 1849 Document.COLUMN_MIME_TYPE,
1862 }; 1850 };
1863 1851
1864 try 1852 cursor = resolver.query (uriObject, projection, null, null,
1865 { 1853 null);
1866 cursor = resolver.query (uriObject, projection, null, null,
1867 null);
1868 }
1869 catch (SecurityException exception)
1870 {
1871 /* A SecurityException can be thrown if Emacs doesn't have
1872 access to uriObject. */
1873 return null;
1874 }
1875 catch (UnsupportedOperationException exception)
1876 {
1877 exception.printStackTrace ();
1878
1879 /* Why is this? */
1880 return null;
1881 }
1882
1883 /* Return the cursor. */ 1854 /* Return the cursor. */
1884 return cursor; 1855 return cursor;
1885 } 1856 }
@@ -1966,11 +1937,15 @@ public final class EmacsService extends Service
1966 1937
1967 Value is NULL upon failure or a parcel file descriptor upon 1938 Value is NULL upon failure or a parcel file descriptor upon
1968 success. Call `ParcelFileDescriptor.close' on this file 1939 success. Call `ParcelFileDescriptor.close' on this file
1969 descriptor instead of using the `close' system call. */ 1940 descriptor instead of using the `close' system call.
1941
1942 FileNotFoundException and/or SecurityException and
1943 UnsupportedOperationException may be thrown upon failure. */
1970 1944
1971 public ParcelFileDescriptor 1945 public ParcelFileDescriptor
1972 openDocument (String uri, String documentId, boolean write, 1946 openDocument (String uri, String documentId, boolean write,
1973 boolean truncate) 1947 boolean truncate)
1948 throws FileNotFoundException
1974 { 1949 {
1975 Uri treeUri, documentUri; 1950 Uri treeUri, documentUri;
1976 String mode; 1951 String mode;
@@ -1984,40 +1959,33 @@ public final class EmacsService extends Service
1984 documentUri 1959 documentUri
1985 = DocumentsContract.buildDocumentUriUsingTree (treeUri, documentId); 1960 = DocumentsContract.buildDocumentUriUsingTree (treeUri, documentId);
1986 1961
1987 try 1962 if (write || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
1988 { 1963 {
1989 if (write || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) 1964 /* Select the mode used to open the file. `rw' means open
1990 { 1965 a stat-able file, while `rwt' means that and to
1991 /* Select the mode used to open the file. `rw' means open 1966 truncate the file as well. */
1992 a stat-able file, while `rwt' means that and to
1993 truncate the file as well. */
1994
1995 if (truncate)
1996 mode = "rwt";
1997 else
1998 mode = "rw";
1999
2000 fileDescriptor
2001 = resolver.openFileDescriptor (documentUri, mode,
2002 null);
2003 }
2004 else
2005 {
2006 /* Select the mode used to open the file. `openFile'
2007 below means always open a stat-able file. */
2008 1967
2009 if (truncate) 1968 if (truncate)
2010 /* Invalid mode! */ 1969 mode = "rwt";
2011 return null; 1970 else
2012 else 1971 mode = "rw";
2013 mode = "r";
2014 1972
2015 fileDescriptor = resolver.openFile (documentUri, mode, null); 1973 fileDescriptor
2016 } 1974 = resolver.openFileDescriptor (documentUri, mode,
1975 null);
2017 } 1976 }
2018 catch (Exception exception) 1977 else
2019 { 1978 {
2020 return null; 1979 /* Select the mode used to open the file. `openFile'
1980 below means always open a stat-able file. */
1981
1982 if (truncate)
1983 /* Invalid mode! */
1984 return null;
1985 else
1986 mode = "r";
1987
1988 fileDescriptor = resolver.openFile (documentUri, mode, null);
2021 } 1989 }
2022 1990
2023 return fileDescriptor; 1991 return fileDescriptor;
@@ -2030,11 +1998,15 @@ public final class EmacsService extends Service
2030 If DOCUMENTID is NULL, create the document inside the root of 1998 If DOCUMENTID is NULL, create the document inside the root of
2031 that tree. 1999 that tree.
2032 2000
2001 Either FileNotFoundException, SecurityException or
2002 UnsupportedOperationException may be thrown upon failure.
2003
2033 Return the document ID of the new file upon success, NULL 2004 Return the document ID of the new file upon success, NULL
2034 otherwise. */ 2005 otherwise. */
2035 2006
2036 public String 2007 public String
2037 createDocument (String uri, String documentId, String name) 2008 createDocument (String uri, String documentId, String name)
2009 throws FileNotFoundException
2038 { 2010 {
2039 String mimeType, separator, mime, extension; 2011 String mimeType, separator, mime, extension;
2040 int index; 2012 int index;
@@ -2072,23 +2044,77 @@ public final class EmacsService extends Service
2072 = DocumentsContract.buildChildDocumentsUriUsingTree (directoryUri, 2044 = DocumentsContract.buildChildDocumentsUriUsingTree (directoryUri,
2073 documentId); 2045 documentId);
2074 2046
2075 try 2047 docUri = DocumentsContract.createDocument (resolver,
2076 { 2048 directoryUri,
2077 docUri = DocumentsContract.createDocument (resolver, 2049 mimeType, name);
2078 directoryUri,
2079 mimeType, name);
2080 2050
2081 if (docUri == null) 2051 if (docUri == null)
2082 return null; 2052 return null;
2083 2053
2084 /* Return the ID of the new document. */ 2054 /* Return the ID of the new document. */
2085 return DocumentsContract.getDocumentId (docUri); 2055 return DocumentsContract.getDocumentId (docUri);
2086 } 2056 }
2087 catch (Exception exception)
2088 {
2089 exception.printStackTrace ();
2090 }
2091 2057
2092 return null; 2058 /* Like `createDocument', but create a directory instead of an
2059 ordinary document. */
2060
2061 public String
2062 createDirectory (String uri, String documentId, String name)
2063 throws FileNotFoundException
2064 {
2065 int index;
2066 Uri directoryUri, docUri;
2067
2068 /* Now parse URI. */
2069 directoryUri = Uri.parse (uri);
2070
2071 if (documentId == null)
2072 documentId = DocumentsContract.getTreeDocumentId (directoryUri);
2073
2074 /* And build a file URI referring to the directory. */
2075
2076 directoryUri
2077 = DocumentsContract.buildChildDocumentsUriUsingTree (directoryUri,
2078 documentId);
2079
2080 /* If name ends with a directory separator character, delete
2081 it. */
2082
2083 if (name.endsWith ("/"))
2084 name = name.substring (0, name.length () - 1);
2085
2086 /* From Android's perspective, directories are just ordinary
2087 documents with the `MIME_TYPE_DIR' type. */
2088
2089 docUri = DocumentsContract.createDocument (resolver,
2090 directoryUri,
2091 Document.MIME_TYPE_DIR,
2092 name);
2093
2094 if (docUri == null)
2095 return null;
2096
2097 /* Return the ID of the new document. */
2098 return DocumentsContract.getDocumentId (docUri);
2099 }
2100
2101 /* Delete the document identified by ID from the document tree
2102 identified by URI. Return 0 upon success and -1 upon
2103 failure. */
2104
2105 public int
2106 deleteDocument (String uri, String id)
2107 throws FileNotFoundException
2108 {
2109 Uri uriObject;
2110
2111 uriObject = Uri.parse (uri);
2112 uriObject = DocumentsContract.buildDocumentUriUsingTree (uriObject,
2113 id);
2114
2115 if (DocumentsContract.deleteDocument (resolver, uriObject))
2116 return 0;
2117
2118 return -1;
2093 } 2119 }
2094}; 2120};