diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 10 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsOpenActivity.java | 9 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 80 |
3 files changed, 91 insertions, 8 deletions
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index 898eaef41a7..654e94b1a7d 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java | |||
| @@ -281,7 +281,7 @@ public final class EmacsNative | |||
| 281 | public static native int[] getSelection (short window); | 281 | public static native int[] getSelection (short window); |
| 282 | 282 | ||
| 283 | 283 | ||
| 284 | /* Graphics functions used as a replacement for potentially buggy | 284 | /* Graphics functions used as replacements for potentially buggy |
| 285 | Android APIs. */ | 285 | Android APIs. */ |
| 286 | 286 | ||
| 287 | public static native void blitRect (Bitmap src, Bitmap dest, int x1, | 287 | public static native void blitRect (Bitmap src, Bitmap dest, int x1, |
| @@ -289,7 +289,6 @@ public final class EmacsNative | |||
| 289 | 289 | ||
| 290 | /* Increment the generation ID of the specified BITMAP, forcing its | 290 | /* Increment the generation ID of the specified BITMAP, forcing its |
| 291 | texture to be re-uploaded to the GPU. */ | 291 | texture to be re-uploaded to the GPU. */ |
| 292 | |||
| 293 | public static native void notifyPixelsChanged (Bitmap bitmap); | 292 | public static native void notifyPixelsChanged (Bitmap bitmap); |
| 294 | 293 | ||
| 295 | 294 | ||
| @@ -313,6 +312,13 @@ public final class EmacsNative | |||
| 313 | in the process. */ | 312 | in the process. */ |
| 314 | public static native boolean ftruncate (int fd); | 313 | public static native boolean ftruncate (int fd); |
| 315 | 314 | ||
| 315 | |||
| 316 | /* Functions that assist in generating content file names. */ | ||
| 317 | |||
| 318 | /* Calculate an 8 digit checksum for the byte array DISPLAYNAME | ||
| 319 | suitable for inclusion in a content file name. */ | ||
| 320 | public static native String displayNameHash (byte[] displayName); | ||
| 321 | |||
| 316 | static | 322 | static |
| 317 | { | 323 | { |
| 318 | /* Older versions of Android cannot link correctly with shared | 324 | /* Older versions of Android cannot link correctly with shared |
diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java b/java/org/gnu/emacs/EmacsOpenActivity.java index 9ae1bf353dd..2cdfa2ec776 100644 --- a/java/org/gnu/emacs/EmacsOpenActivity.java +++ b/java/org/gnu/emacs/EmacsOpenActivity.java | |||
| @@ -252,7 +252,7 @@ public final class EmacsOpenActivity extends Activity | |||
| 252 | 252 | ||
| 253 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) | 253 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) |
| 254 | { | 254 | { |
| 255 | content = EmacsService.buildContentName (uri); | 255 | content = EmacsService.buildContentName (uri, getContentResolver ()); |
| 256 | return content; | 256 | return content; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| @@ -423,6 +423,7 @@ public final class EmacsOpenActivity extends Activity | |||
| 423 | /* Obtain the intent that started Emacs. */ | 423 | /* Obtain the intent that started Emacs. */ |
| 424 | intent = getIntent (); | 424 | intent = getIntent (); |
| 425 | action = intent.getAction (); | 425 | action = intent.getAction (); |
| 426 | resolver = getContentResolver (); | ||
| 426 | 427 | ||
| 427 | if (action == null) | 428 | if (action == null) |
| 428 | { | 429 | { |
| @@ -536,7 +537,7 @@ public final class EmacsOpenActivity extends Activity | |||
| 536 | if ((scheme = uri.getScheme ()) != null | 537 | if ((scheme = uri.getScheme ()) != null |
| 537 | && scheme.equals ("content")) | 538 | && scheme.equals ("content")) |
| 538 | { | 539 | { |
| 539 | tem1 = EmacsService.buildContentName (uri); | 540 | tem1 = EmacsService.buildContentName (uri, resolver); |
| 540 | attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\") | 541 | attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\") |
| 541 | .replace ("\"", "\\\"") | 542 | .replace ("\"", "\\\"") |
| 542 | .replace ("$", "\\$")) | 543 | .replace ("$", "\\$")) |
| @@ -568,7 +569,8 @@ public final class EmacsOpenActivity extends Activity | |||
| 568 | && (scheme = uri.getScheme ()) != null | 569 | && (scheme = uri.getScheme ()) != null |
| 569 | && scheme.equals ("content")) | 570 | && scheme.equals ("content")) |
| 570 | { | 571 | { |
| 571 | tem1 = EmacsService.buildContentName (uri); | 572 | tem1 |
| 573 | = EmacsService.buildContentName (uri, resolver); | ||
| 572 | builder.append ("\""); | 574 | builder.append ("\""); |
| 573 | builder.append (tem1.replace ("\\", "\\\\") | 575 | builder.append (tem1.replace ("\\", "\\\\") |
| 574 | .replace ("\"", "\\\"") | 576 | .replace ("\"", "\\\"") |
| @@ -609,7 +611,6 @@ public final class EmacsOpenActivity extends Activity | |||
| 609 | underlying file, but it cannot be found without | 611 | underlying file, but it cannot be found without |
| 610 | opening the file and doing readlink on its file | 612 | opening the file and doing readlink on its file |
| 611 | descriptor in /proc/self/fd. */ | 613 | descriptor in /proc/self/fd. */ |
| 612 | resolver = getContentResolver (); | ||
| 613 | fd = null; | 614 | fd = null; |
| 614 | 615 | ||
| 615 | try | 616 | try |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 9bc40d63311..19aa3dee456 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -79,6 +79,7 @@ import android.os.VibrationEffect; | |||
| 79 | 79 | ||
| 80 | import android.provider.DocumentsContract; | 80 | import android.provider.DocumentsContract; |
| 81 | import android.provider.DocumentsContract.Document; | 81 | import android.provider.DocumentsContract.Document; |
| 82 | import android.provider.OpenableColumns; | ||
| 82 | import android.provider.Settings; | 83 | import android.provider.Settings; |
| 83 | 84 | ||
| 84 | import android.util.Log; | 85 | import android.util.Log; |
| @@ -1033,22 +1034,87 @@ public final class EmacsService extends Service | |||
| 1033 | return false; | 1034 | return false; |
| 1034 | } | 1035 | } |
| 1035 | 1036 | ||
| 1037 | /* Return a 8 character checksum for the string STRING, after encoding | ||
| 1038 | as UTF-8 data. */ | ||
| 1039 | |||
| 1040 | public static String | ||
| 1041 | getDisplayNameHash (String string) | ||
| 1042 | { | ||
| 1043 | byte[] encoded; | ||
| 1044 | |||
| 1045 | try | ||
| 1046 | { | ||
| 1047 | encoded = string.getBytes ("UTF-8"); | ||
| 1048 | return EmacsNative.displayNameHash (encoded); | ||
| 1049 | } | ||
| 1050 | catch (UnsupportedEncodingException exception) | ||
| 1051 | { | ||
| 1052 | /* This should be impossible. */ | ||
| 1053 | return "error"; | ||
| 1054 | } | ||
| 1055 | } | ||
| 1056 | |||
| 1036 | /* Build a content file name for URI. | 1057 | /* Build a content file name for URI. |
| 1037 | 1058 | ||
| 1038 | Return a file name within the /contents/by-authority | 1059 | Return a file name within the /contents/by-authority |
| 1039 | pseudo-directory that `android_get_content_name' can then | 1060 | pseudo-directory that `android_get_content_name' can then |
| 1040 | transform back into an encoded URI. | 1061 | transform back into an encoded URI. |
| 1041 | 1062 | ||
| 1063 | If a display name can be requested from URI (using the resolver | ||
| 1064 | RESOLVER), append it to this file name. | ||
| 1065 | |||
| 1042 | A content name consists of any number of unencoded path segments | 1066 | A content name consists of any number of unencoded path segments |
| 1043 | separated by `/' characters, possibly followed by a question mark | 1067 | separated by `/' characters, possibly followed by a question mark |
| 1044 | and an encoded query string. */ | 1068 | and an encoded query string. */ |
| 1045 | 1069 | ||
| 1046 | public static String | 1070 | public static String |
| 1047 | buildContentName (Uri uri) | 1071 | buildContentName (Uri uri, ContentResolver resolver) |
| 1048 | { | 1072 | { |
| 1049 | StringBuilder builder; | 1073 | StringBuilder builder; |
| 1074 | String displayName; | ||
| 1075 | String[] projection; | ||
| 1076 | Cursor cursor; | ||
| 1077 | int column; | ||
| 1078 | |||
| 1079 | displayName = null; | ||
| 1080 | cursor = null; | ||
| 1050 | 1081 | ||
| 1051 | builder = new StringBuilder ("/content/by-authority/"); | 1082 | try |
| 1083 | { | ||
| 1084 | projection = new String[] { OpenableColumns.DISPLAY_NAME, }; | ||
| 1085 | cursor = resolver.query (uri, projection, null, null, null); | ||
| 1086 | |||
| 1087 | if (cursor != null) | ||
| 1088 | { | ||
| 1089 | cursor.moveToFirst (); | ||
| 1090 | column | ||
| 1091 | = cursor.getColumnIndexOrThrow (OpenableColumns.DISPLAY_NAME); | ||
| 1092 | displayName | ||
| 1093 | = cursor.getString (column); | ||
| 1094 | |||
| 1095 | /* Verify that the display name is valid, i.e. it | ||
| 1096 | contains no characters unsuitable for a file name and | ||
| 1097 | is nonempty. */ | ||
| 1098 | if (displayName.isEmpty () || displayName.contains ("/")) | ||
| 1099 | displayName = null; | ||
| 1100 | } | ||
| 1101 | } | ||
| 1102 | catch (Exception e) | ||
| 1103 | { | ||
| 1104 | /* Ignored. */ | ||
| 1105 | } | ||
| 1106 | finally | ||
| 1107 | { | ||
| 1108 | if (cursor != null) | ||
| 1109 | cursor.close (); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | /* If a display name is available, at this point it should be the | ||
| 1113 | value of displayName. */ | ||
| 1114 | |||
| 1115 | builder = new StringBuilder (displayName != null | ||
| 1116 | ? "/content/by-authority-named/" | ||
| 1117 | : "/content/by-authority/"); | ||
| 1052 | builder.append (uri.getAuthority ()); | 1118 | builder.append (uri.getAuthority ()); |
| 1053 | 1119 | ||
| 1054 | /* First, append each path segment. */ | 1120 | /* First, append each path segment. */ |
| @@ -1065,6 +1131,16 @@ public final class EmacsService extends Service | |||
| 1065 | if (uri.getEncodedQuery () != null) | 1131 | if (uri.getEncodedQuery () != null) |
| 1066 | builder.append ('?').append (uri.getEncodedQuery ()); | 1132 | builder.append ('?').append (uri.getEncodedQuery ()); |
| 1067 | 1133 | ||
| 1134 | /* Append the display name. */ | ||
| 1135 | |||
| 1136 | if (displayName != null) | ||
| 1137 | { | ||
| 1138 | builder.append ('/'); | ||
| 1139 | builder.append (getDisplayNameHash (displayName)); | ||
| 1140 | builder.append ('/'); | ||
| 1141 | builder.append (displayName); | ||
| 1142 | } | ||
| 1143 | |||
| 1068 | return builder.toString (); | 1144 | return builder.toString (); |
| 1069 | } | 1145 | } |
| 1070 | 1146 | ||