aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorPo Lu2023-02-21 15:28:06 +0800
committerPo Lu2023-02-21 15:28:06 +0800
commit7aa4ffddd842e495d1ae388afff12075317ecb07 (patch)
tree9ba8cb2c232665ee59113494f7e35eeb33ab8619 /java
parentd197d7349121b972d50e37d66017567bf6cba652 (diff)
downloademacs-7aa4ffddd842e495d1ae388afff12075317ecb07.tar.gz
emacs-7aa4ffddd842e495d1ae388afff12075317ecb07.zip
Update Android port
* doc/emacs/android.texi (Android Startup): Document `content' special directory. * java/debug.sh (is_root): Improve /bin/tee detection. * java/org/gnu/emacs/EmacsNative.java (EmacsNative): New function `dup'. * java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity) (checkReadableOrCopy, onCreate): Create content directory names when the file is not readable. * java/org/gnu/emacs/EmacsService.java (EmacsService) (openContentUri, checkContentUri): New functions. * src/android.c (struct android_emacs_service): New methods. (android_content_name_p, android_get_content_name) (android_check_content_access): New function. (android_fstatat, android_open): Implement opening content URIs. (dup): Export to Java. (android_init_emacs_service): Initialize new methods. (android_faccessat): Implement content file names.
Diffstat (limited to 'java')
-rwxr-xr-xjava/debug.sh2
-rw-r--r--java/org/gnu/emacs/EmacsNative.java4
-rw-r--r--java/org/gnu/emacs/EmacsOpenActivity.java42
-rw-r--r--java/org/gnu/emacs/EmacsService.java119
4 files changed, 160 insertions, 7 deletions
diff --git a/java/debug.sh b/java/debug.sh
index 30e5a94eee5..f07bb98ed7d 100755
--- a/java/debug.sh
+++ b/java/debug.sh
@@ -281,7 +281,7 @@ else
281 # Upload the specified gdbserver binary to the device. 281 # Upload the specified gdbserver binary to the device.
282 adb -s $device push "$gdbserver" "$gdbserver_bin" 282 adb -s $device push "$gdbserver" "$gdbserver_bin"
283 283
284 if (adb -s $device pull /system/bin/tee /dev/null &> /dev/null); then 284 if adb -s $device shell ls /system/bin/tee; then
285 # Copy it to the user directory. 285 # Copy it to the user directory.
286 adb -s $device shell "$gdbserver_cat" 286 adb -s $device shell "$gdbserver_cat"
287 adb -s $device shell "run-as $package chmod +x gdbserver" 287 adb -s $device shell "run-as $package chmod +x gdbserver"
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java
index ef1a0e75a5c..f0917a68120 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -31,6 +31,10 @@ public class EmacsNative
31 initialization. */ 31 initialization. */
32 private static final String[] libraryDeps; 32 private static final String[] libraryDeps;
33 33
34
35 /* Like `dup' in C. */
36 public static native int dup (int fd);
37
34 /* Obtain the fingerprint of this build of Emacs. The fingerprint 38 /* Obtain the fingerprint of this build of Emacs. The fingerprint
35 can be used to determine the dump file name. */ 39 can be used to determine the dump file name. */
36 public static native String getFingerprint (); 40 public static native String getFingerprint ();
diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java b/java/org/gnu/emacs/EmacsOpenActivity.java
index c8501d91025..87ce454a816 100644
--- a/java/org/gnu/emacs/EmacsOpenActivity.java
+++ b/java/org/gnu/emacs/EmacsOpenActivity.java
@@ -57,6 +57,8 @@ import android.os.Build;
57import android.os.Bundle; 57import android.os.Bundle;
58import android.os.ParcelFileDescriptor; 58import android.os.ParcelFileDescriptor;
59 59
60import android.util.Log;
61
60import java.io.File; 62import java.io.File;
61import java.io.FileInputStream; 63import java.io.FileInputStream;
62import java.io.FileNotFoundException; 64import java.io.FileNotFoundException;
@@ -69,6 +71,8 @@ import java.io.UnsupportedEncodingException;
69public class EmacsOpenActivity extends Activity 71public class EmacsOpenActivity extends Activity
70 implements DialogInterface.OnClickListener 72 implements DialogInterface.OnClickListener
71{ 73{
74 private static final String TAG = "EmacsOpenActivity";
75
72 private class EmacsClientThread extends Thread 76 private class EmacsClientThread extends Thread
73 { 77 {
74 private ProcessBuilder builder; 78 private ProcessBuilder builder;
@@ -178,12 +182,16 @@ public class EmacsOpenActivity extends Activity
178 dialog.show (); 182 dialog.show ();
179 } 183 }
180 184
181 /* Check that the specified FILE is readable. If it is not, then 185 /* Check that the specified FILE is readable. If Android 4.4 or
182 copy the file in FD to a location in the system cache 186 later is being used, return URI formatted into a `/content/' file
183 directory and return the name of that file. */ 187 name.
188
189 If it is not, then copy the file in FD to a location in the
190 system cache directory and return the name of that file. */
184 191
185 private String 192 private String
186 checkReadableOrCopy (String file, ParcelFileDescriptor fd) 193 checkReadableOrCopy (String file, ParcelFileDescriptor fd,
194 Uri uri)
187 throws IOException, FileNotFoundException 195 throws IOException, FileNotFoundException
188 { 196 {
189 File inFile; 197 File inFile;
@@ -191,12 +199,34 @@ public class EmacsOpenActivity extends Activity
191 InputStream stream; 199 InputStream stream;
192 byte buffer[]; 200 byte buffer[];
193 int read; 201 int read;
202 String content;
203
204 Log.d (TAG, "checkReadableOrCopy: " + file);
194 205
195 inFile = new File (file); 206 inFile = new File (file);
196 207
197 if (inFile.setReadable (true)) 208 if (inFile.canRead ())
198 return file; 209 return file;
199 210
211 Log.d (TAG, "checkReadableOrCopy: NO");
212
213 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
214 {
215 content = "/content/" + uri.getEncodedAuthority ();
216
217 for (String segment : uri.getPathSegments ())
218 content += "/" + Uri.encode (segment);
219
220 /* Append the URI query. */
221
222 if (uri.getEncodedQuery () != null)
223 content += "?" + uri.getEncodedQuery ();
224
225 Log.d (TAG, "checkReadableOrCopy: " + content);
226
227 return content;
228 }
229
200 /* inFile is now the file being written to. */ 230 /* inFile is now the file being written to. */
201 inFile = new File (getCacheDir (), inFile.getName ()); 231 inFile = new File (getCacheDir (), inFile.getName ());
202 buffer = new byte[4098]; 232 buffer = new byte[4098];
@@ -398,7 +428,7 @@ public class EmacsOpenActivity extends Activity
398 if (names != null) 428 if (names != null)
399 fileName = new String (names, "UTF-8"); 429 fileName = new String (names, "UTF-8");
400 430
401 fileName = checkReadableOrCopy (fileName, fd); 431 fileName = checkReadableOrCopy (fileName, fd, uri);
402 } 432 }
403 catch (FileNotFoundException exception) 433 catch (FileNotFoundException exception)
404 { 434 {
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index ba6ec485d62..c9701ff2990 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -19,7 +19,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20package org.gnu.emacs; 20package org.gnu.emacs;
21 21
22import java.io.FileNotFoundException;
22import java.io.IOException; 23import java.io.IOException;
24import java.io.UnsupportedEncodingException;
25
23import java.util.List; 26import java.util.List;
24import java.util.ArrayList; 27import java.util.ArrayList;
25 28
@@ -41,22 +44,31 @@ import android.app.Service;
41 44
42import android.content.ClipboardManager; 45import android.content.ClipboardManager;
43import android.content.Context; 46import android.content.Context;
47import android.content.ContentResolver;
44import android.content.Intent; 48import android.content.Intent;
45import android.content.pm.ApplicationInfo; 49import android.content.pm.ApplicationInfo;
46import android.content.pm.PackageManager.ApplicationInfoFlags; 50import android.content.pm.PackageManager.ApplicationInfoFlags;
47import android.content.pm.PackageManager; 51import android.content.pm.PackageManager;
48import android.content.res.AssetManager; 52import android.content.res.AssetManager;
49 53
54import android.database.Cursor;
55import android.database.MatrixCursor;
56
57
50import android.net.Uri; 58import android.net.Uri;
51 59
52import android.os.Build; 60import android.os.Build;
53import android.os.Looper; 61import android.os.Looper;
54import android.os.IBinder; 62import android.os.IBinder;
55import android.os.Handler; 63import android.os.Handler;
64import android.os.ParcelFileDescriptor;
56import android.os.Vibrator; 65import android.os.Vibrator;
57import android.os.VibratorManager; 66import android.os.VibratorManager;
58import android.os.VibrationEffect; 67import android.os.VibrationEffect;
59 68
69import android.provider.DocumentsContract;
70import android.provider.DocumentsContract.Document;
71
60import android.util.Log; 72import android.util.Log;
61import android.util.DisplayMetrics; 73import android.util.DisplayMetrics;
62 74
@@ -79,6 +91,7 @@ public class EmacsService extends Service
79 91
80 private EmacsThread thread; 92 private EmacsThread thread;
81 private Handler handler; 93 private Handler handler;
94 private ContentResolver resolver;
82 95
83 /* Keep this in synch with androidgui.h. */ 96 /* Keep this in synch with androidgui.h. */
84 public static final int IC_MODE_NULL = 0; 97 public static final int IC_MODE_NULL = 0;
@@ -193,6 +206,7 @@ public class EmacsService extends Service
193 metrics = getResources ().getDisplayMetrics (); 206 metrics = getResources ().getDisplayMetrics ();
194 pixelDensityX = metrics.xdpi; 207 pixelDensityX = metrics.xdpi;
195 pixelDensityY = metrics.ydpi; 208 pixelDensityY = metrics.ydpi;
209 resolver = getContentResolver ();
196 210
197 try 211 try
198 { 212 {
@@ -643,4 +657,109 @@ public class EmacsService extends Service
643 window.view.setICMode (icMode); 657 window.view.setICMode (icMode);
644 window.view.imManager.restartInput (window.view); 658 window.view.imManager.restartInput (window.view);
645 } 659 }
660
661 /* Open a content URI described by the bytes BYTES, a non-terminated
662 string; make it writable if WRITABLE, and readable if READABLE.
663 Truncate the file if TRUNCATE.
664
665 Value is the resulting file descriptor or -1 upon failure. */
666
667 public int
668 openContentUri (byte[] bytes, boolean writable, boolean readable,
669 boolean truncate)
670 {
671 String name, mode;
672 ParcelFileDescriptor fd;
673 int i;
674
675 /* Figure out the file access mode. */
676
677 mode = "";
678
679 if (readable)
680 mode += "r";
681
682 if (writable)
683 mode += "w";
684
685 if (truncate)
686 mode += "t";
687
688 /* Try to open an associated ParcelFileDescriptor. */
689
690 try
691 {
692 /* The usual file name encoding question rears its ugly head
693 again. */
694 name = new String (bytes, "UTF-8");
695 Log.d (TAG, "openContentUri: " + Uri.parse (name));
696
697 fd = resolver.openFileDescriptor (Uri.parse (name), mode);
698
699 /* Use detachFd on newer versions of Android or plain old
700 dup. */
701
702 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1)
703 {
704 i = fd.detachFd ();
705 fd.close ();
706
707 return i;
708 }
709 else
710 {
711 i = EmacsNative.dup (fd.getFd ());
712 fd.close ();
713
714 return i;
715 }
716 }
717 catch (Exception exception)
718 {
719 return -1;
720 }
721 }
722
723 public boolean
724 checkContentUri (byte[] string, boolean readable, boolean writable)
725 {
726 String mode, name;
727 ParcelFileDescriptor fd;
728
729 /* Decode this into a URI. */
730
731 try
732 {
733 /* The usual file name encoding question rears its ugly head
734 again. */
735 name = new String (string, "UTF-8");
736 Log.d (TAG, "checkContentUri: " + Uri.parse (name));
737 }
738 catch (UnsupportedEncodingException exception)
739 {
740 name = null;
741 throw new RuntimeException (exception);
742 }
743
744 mode = "r";
745
746 if (writable)
747 mode += "w";
748
749 try
750 {
751 fd = resolver.openFileDescriptor (Uri.parse (name), mode);
752 fd.close ();
753
754 Log.d (TAG, "checkContentUri: YES");
755
756 return true;
757 }
758 catch (Exception exception)
759 {
760 Log.d (TAG, "checkContentUri: NO");
761 Log.d (TAG, exception.toString ());
762 return false;
763 }
764 }
646}; 765};