aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2024-05-08 16:03:49 +0800
committerPo Lu2024-05-08 16:03:49 +0800
commite020f4e9ce5d98438033fea098d943c311b0fa3d (patch)
tree9d7828ac6f6abe3405c9432bc3c4c1018d5ab54a
parentd0b36be59ab9840eebbda45609bc8c075ece40c0 (diff)
downloademacs-e020f4e9ce5d98438033fea098d943c311b0fa3d.tar.gz
emacs-e020f4e9ce5d98438033fea098d943c311b0fa3d.zip
Fix hang after failed yank-media on Android
* java/org/gnu/emacs/EmacsClipboard.java (getClipboardTargets) (getClipboardData): * java/org/gnu/emacs/EmacsSdk11Clipboard.java (getClipboardTargets, getClipboardData): * java/org/gnu/emacs/EmacsSdk8Clipboard.java (getClipboardTargets, getClipboardData): Return string data as Strings rather than byte arrays. * src/androidselect.c (android_init_emacs_clipboard) (Fandroid_get_clipboard_targets): Adjust to match. (extract_fd_offsets): Remove duplicated semicolon. (Fandroid_get_clipboard_data): Call unblock_input before returning if extract_fd_offsets fails.
-rw-r--r--java/org/gnu/emacs/EmacsClipboard.java4
-rw-r--r--java/org/gnu/emacs/EmacsSdk11Clipboard.java30
-rw-r--r--java/org/gnu/emacs/EmacsSdk8Clipboard.java4
-rw-r--r--src/androidselect.c74
4 files changed, 45 insertions, 67 deletions
diff --git a/java/org/gnu/emacs/EmacsClipboard.java b/java/org/gnu/emacs/EmacsClipboard.java
index f27d96129ef..86553f478ed 100644
--- a/java/org/gnu/emacs/EmacsClipboard.java
+++ b/java/org/gnu/emacs/EmacsClipboard.java
@@ -32,8 +32,8 @@ public abstract class EmacsClipboard
32 public abstract boolean clipboardExists (); 32 public abstract boolean clipboardExists ();
33 public abstract byte[] getClipboard (); 33 public abstract byte[] getClipboard ();
34 34
35 public abstract byte[][] getClipboardTargets (); 35 public abstract String[] getClipboardTargets ();
36 public abstract AssetFileDescriptor getClipboardData (byte[] target); 36 public abstract AssetFileDescriptor getClipboardData (String target);
37 37
38 /* Create the correct kind of clipboard for this system. */ 38 /* Create the correct kind of clipboard for this system. */
39 39
diff --git a/java/org/gnu/emacs/EmacsSdk11Clipboard.java b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
index 71381b0f114..dfc714476ec 100644
--- a/java/org/gnu/emacs/EmacsSdk11Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
@@ -172,12 +172,12 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
172 clipboard, or NULL if there are none. */ 172 clipboard, or NULL if there are none. */
173 173
174 @Override 174 @Override
175 public byte[][] 175 public String[]
176 getClipboardTargets () 176 getClipboardTargets ()
177 { 177 {
178 ClipData clip; 178 ClipData clip;
179 ClipDescription description; 179 ClipDescription description;
180 byte[][] typeArray; 180 String[] typeArray;
181 int i; 181 int i;
182 182
183 /* N.B. that Android calls the clipboard the ``primary clip''; it 183 /* N.B. that Android calls the clipboard the ``primary clip''; it
@@ -189,17 +189,10 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
189 189
190 description = clip.getDescription (); 190 description = clip.getDescription ();
191 i = description.getMimeTypeCount (); 191 i = description.getMimeTypeCount ();
192 typeArray = new byte[i][i]; 192 typeArray = new String[i];
193 193
194 try 194 for (i = 0; i < description.getMimeTypeCount (); ++i)
195 { 195 typeArray[i] = description.getMimeType (i);
196 for (i = 0; i < description.getMimeTypeCount (); ++i)
197 typeArray[i] = description.getMimeType (i).getBytes ("UTF-8");
198 }
199 catch (UnsupportedEncodingException exception)
200 {
201 return null;
202 }
203 196
204 return typeArray; 197 return typeArray;
205 } 198 }
@@ -219,26 +212,17 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
219 212
220 @Override 213 @Override
221 public AssetFileDescriptor 214 public AssetFileDescriptor
222 getClipboardData (byte[] target) 215 getClipboardData (String target)
223 { 216 {
224 ClipData data; 217 ClipData data;
225 String mimeType; 218 String mimeType;
226 AssetFileDescriptor assetFd; 219 AssetFileDescriptor assetFd;
227 Uri uri; 220 Uri uri;
228 221
229 /* Decode the target given by Emacs. */
230 try
231 {
232 mimeType = new String (target, "UTF-8");
233 }
234 catch (UnsupportedEncodingException exception)
235 {
236 return null;
237 }
238
239 /* Now obtain the clipboard data and the data corresponding to 222 /* Now obtain the clipboard data and the data corresponding to
240 that MIME type. */ 223 that MIME type. */
241 224
225 mimeType = target;
242 data = manager.getPrimaryClip (); 226 data = manager.getPrimaryClip ();
243 227
244 if (data == null || data.getItemCount () < 1) 228 if (data == null || data.getItemCount () < 1)
diff --git a/java/org/gnu/emacs/EmacsSdk8Clipboard.java b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
index 3d0504b1924..344ec6f7997 100644
--- a/java/org/gnu/emacs/EmacsSdk8Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
@@ -122,7 +122,7 @@ public final class EmacsSdk8Clipboard extends EmacsClipboard
122 clipboard, or NULL if there are none. */ 122 clipboard, or NULL if there are none. */
123 123
124 @Override 124 @Override
125 public byte[][] 125 public String[]
126 getClipboardTargets () 126 getClipboardTargets ()
127 { 127 {
128 return null; 128 return null;
@@ -143,7 +143,7 @@ public final class EmacsSdk8Clipboard extends EmacsClipboard
143 143
144 @Override 144 @Override
145 public AssetFileDescriptor 145 public AssetFileDescriptor
146 getClipboardData (byte[] target) 146 getClipboardData (String target)
147 { 147 {
148 return null; 148 return null;
149 } 149 }
diff --git a/src/androidselect.c b/src/androidselect.c
index d9c35746f11..7c93607848a 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -99,9 +99,10 @@ android_init_emacs_clipboard (void)
99 FIND_METHOD (clipboard_exists, "clipboardExists", "()Z"); 99 FIND_METHOD (clipboard_exists, "clipboardExists", "()Z");
100 FIND_METHOD (get_clipboard, "getClipboard", "()[B"); 100 FIND_METHOD (get_clipboard, "getClipboard", "()[B");
101 FIND_METHOD (get_clipboard_targets, "getClipboardTargets", 101 FIND_METHOD (get_clipboard_targets, "getClipboardTargets",
102 "()[[B"); 102 "()[Ljava/lang/String;");
103 FIND_METHOD (get_clipboard_data, "getClipboardData", 103 FIND_METHOD (get_clipboard_data, "getClipboardData",
104 "([B)Landroid/content/res/AssetFileDescriptor;"); 104 "(Ljava/lang/String;)Landroid/content/res/"
105 "AssetFileDescriptor;");
105 106
106 clipboard_class.make_clipboard 107 clipboard_class.make_clipboard
107 = (*android_java_env)->GetStaticMethodID (android_java_env, 108 = (*android_java_env)->GetStaticMethodID (android_java_env,
@@ -283,11 +284,11 @@ Value is a list of MIME types as strings, each defining a single extra
283data type available from the clipboard. */) 284data type available from the clipboard. */)
284 (void) 285 (void)
285{ 286{
286 jarray bytes_array; 287 jarray all_targets;
287 jbyteArray bytes; 288 jstring string;
288 jmethodID method; 289 jmethodID method;
289 size_t length, length1, i; 290 size_t length, i;
290 jbyte *data; 291 const char *data;
291 Lisp_Object targets, tem; 292 Lisp_Object targets, tem;
292 293
293 if (!android_init_gui) 294 if (!android_init_gui)
@@ -296,44 +297,42 @@ data type available from the clipboard. */)
296 targets = Qnil; 297 targets = Qnil;
297 block_input (); 298 block_input ();
298 method = clipboard_class.get_clipboard_targets; 299 method = clipboard_class.get_clipboard_targets;
299 bytes_array = (*android_java_env)->CallObjectMethod (android_java_env, 300 all_targets = (*android_java_env)->CallObjectMethod (android_java_env,
300 clipboard, method); 301 clipboard, method);
301 android_exception_check (); 302 android_exception_check ();
302 303
303 if (!bytes_array) 304 if (!all_targets)
304 goto fail; 305 goto fail;
305 306
306 length = (*android_java_env)->GetArrayLength (android_java_env, 307 length = (*android_java_env)->GetArrayLength (android_java_env,
307 bytes_array); 308 all_targets);
308 for (i = 0; i < length; ++i) 309 for (i = 0; i < length; ++i)
309 { 310 {
310 /* Retrieve the MIME type. */ 311 /* Retrieve the MIME type. */
311 bytes 312 string
312 = (*android_java_env)->GetObjectArrayElement (android_java_env, 313 = (*android_java_env)->GetObjectArrayElement (android_java_env,
313 bytes_array, i); 314 all_targets, i);
314 android_exception_check_nonnull (bytes, bytes_array); 315 android_exception_check_nonnull (string, all_targets);
315 316
316 /* Cons it onto the list of targets. */ 317 /* Cons it onto the list of targets. */
317 length1 = (*android_java_env)->GetArrayLength (android_java_env, 318 data = (*android_java_env)->GetStringUTFChars (android_java_env,
318 bytes); 319 string, NULL);
319 data = (*android_java_env)->GetByteArrayElements (android_java_env, 320 android_exception_check_nonnull_1 ((void *) data, string,
320 bytes, NULL); 321 all_targets);
321 android_exception_check_nonnull_1 (data, bytes, bytes_array);
322 322
323 /* Decode the string. */ 323 /* Decode the string. */
324 tem = make_unibyte_string ((char *) data, length1); 324 tem = build_unibyte_string ((char *) data);
325 tem = code_convert_string_norecord (tem, Qutf_8, false); 325 tem = code_convert_string_norecord (tem, Qandroid_jni, false);
326 targets = Fcons (tem, targets); 326 targets = Fcons (tem, targets);
327 327
328 /* Delete the retrieved data. */ 328 /* Delete the retrieved data. */
329 (*android_java_env)->ReleaseByteArrayElements (android_java_env, 329 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
330 bytes, data, 330 string, data);
331 JNI_ABORT); 331 ANDROID_DELETE_LOCAL_REF (string);
332 ANDROID_DELETE_LOCAL_REF (bytes);
333 } 332 }
334 unblock_input (); 333 unblock_input ();
335 334
336 ANDROID_DELETE_LOCAL_REF (bytes_array); 335 ANDROID_DELETE_LOCAL_REF (all_targets);
337 return Fnreverse (targets); 336 return Fnreverse (targets);
338 337
339 fail: 338 fail:
@@ -432,7 +431,7 @@ extract_fd_offsets (jobject afd, int *fd, jlong *offset, jlong *length)
432#if __ANDROID_API__ <= 11 431#if __ANDROID_API__ <= 11
433 static int (*jniGetFDFromFileDescriptor) (JNIEnv *, jobject); 432 static int (*jniGetFDFromFileDescriptor) (JNIEnv *, jobject);
434#endif /* __ANDROID_API__ <= 11 */ 433#endif /* __ANDROID_API__ <= 11 */
435 static int (*AFileDescriptor_getFd) (JNIEnv *, jobject);; 434 static int (*AFileDescriptor_getFd) (JNIEnv *, jobject);
436 jmethodID method; 435 jmethodID method;
437 436
438 method = asset_fd_class.get_start_offset; 437 method = asset_fd_class.get_start_offset;
@@ -538,7 +537,7 @@ does not have any corresponding data. In that case, use
538 (Lisp_Object type) 537 (Lisp_Object type)
539{ 538{
540 jobject afd; 539 jobject afd;
541 jbyteArray bytes; 540 jstring mime_type;
542 jmethodID method; 541 jmethodID method;
543 int fd; 542 int fd;
544 ptrdiff_t rc; 543 ptrdiff_t rc;
@@ -549,25 +548,17 @@ does not have any corresponding data. In that case, use
549 if (!android_init_gui) 548 if (!android_init_gui)
550 error ("No Android display connection!"); 549 error ("No Android display connection!");
551 550
552 /* Encode the string as UTF-8. */
553 CHECK_STRING (type); 551 CHECK_STRING (type);
554 type = ENCODE_UTF_8 (type);
555 552
556 /* Then give it to the selection code. */ 553 /* Convert TYPE into a Java string. */
557 block_input (); 554 block_input ();
558 bytes = (*android_java_env)->NewByteArray (android_java_env, 555 mime_type = android_build_string (type, NULL);
559 SBYTES (type));
560 (*android_java_env)->SetByteArrayRegion (android_java_env, bytes,
561 0, SBYTES (type),
562 (jbyte *) SDATA (type));
563 android_exception_check ();
564
565 method = clipboard_class.get_clipboard_data; 556 method = clipboard_class.get_clipboard_data;
566 afd = (*android_java_env)->CallObjectMethod (android_java_env, 557 afd = (*android_java_env)->CallObjectMethod (android_java_env,
567 clipboard, method, 558 clipboard, method,
568 bytes); 559 mime_type);
569 android_exception_check_1 (bytes); 560 android_exception_check_1 (mime_type);
570 ANDROID_DELETE_LOCAL_REF (bytes); 561 ANDROID_DELETE_LOCAL_REF (mime_type);
571 562
572 if (!afd) 563 if (!afd)
573 goto fail; 564 goto fail;
@@ -578,7 +569,10 @@ does not have any corresponding data. In that case, use
578 record_unwind_protect_ptr (close_asset_fd, &afd); 569 record_unwind_protect_ptr (close_asset_fd, &afd);
579 570
580 if (extract_fd_offsets (afd, &fd, &offset, &length)) 571 if (extract_fd_offsets (afd, &fd, &offset, &length))
581 return unbind_to (ref, Qnil); 572 {
573 unblock_input ();
574 return unbind_to (ref, Qnil);
575 }
582 unblock_input (); 576 unblock_input ();
583 577
584 /* Now begin reading from fd. */ 578 /* Now begin reading from fd. */