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.
This commit is contained in:
Po Lu 2024-05-08 16:03:49 +08:00
parent d0b36be59a
commit e020f4e9ce
4 changed files with 45 additions and 67 deletions

View file

@ -32,8 +32,8 @@ public abstract class EmacsClipboard
public abstract boolean clipboardExists ();
public abstract byte[] getClipboard ();
public abstract byte[][] getClipboardTargets ();
public abstract AssetFileDescriptor getClipboardData (byte[] target);
public abstract String[] getClipboardTargets ();
public abstract AssetFileDescriptor getClipboardData (String target);
/* Create the correct kind of clipboard for this system. */

View file

@ -172,12 +172,12 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
clipboard, or NULL if there are none. */
@Override
public byte[][]
public String[]
getClipboardTargets ()
{
ClipData clip;
ClipDescription description;
byte[][] typeArray;
String[] typeArray;
int i;
/* N.B. that Android calls the clipboard the ``primary clip''; it
@ -189,17 +189,10 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
description = clip.getDescription ();
i = description.getMimeTypeCount ();
typeArray = new byte[i][i];
typeArray = new String[i];
try
{
for (i = 0; i < description.getMimeTypeCount (); ++i)
typeArray[i] = description.getMimeType (i).getBytes ("UTF-8");
}
catch (UnsupportedEncodingException exception)
{
return null;
}
for (i = 0; i < description.getMimeTypeCount (); ++i)
typeArray[i] = description.getMimeType (i);
return typeArray;
}
@ -219,26 +212,17 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
@Override
public AssetFileDescriptor
getClipboardData (byte[] target)
getClipboardData (String target)
{
ClipData data;
String mimeType;
AssetFileDescriptor assetFd;
Uri uri;
/* Decode the target given by Emacs. */
try
{
mimeType = new String (target, "UTF-8");
}
catch (UnsupportedEncodingException exception)
{
return null;
}
/* Now obtain the clipboard data and the data corresponding to
that MIME type. */
mimeType = target;
data = manager.getPrimaryClip ();
if (data == null || data.getItemCount () < 1)

View file

@ -122,7 +122,7 @@ public final class EmacsSdk8Clipboard extends EmacsClipboard
clipboard, or NULL if there are none. */
@Override
public byte[][]
public String[]
getClipboardTargets ()
{
return null;
@ -143,7 +143,7 @@ public final class EmacsSdk8Clipboard extends EmacsClipboard
@Override
public AssetFileDescriptor
getClipboardData (byte[] target)
getClipboardData (String target)
{
return null;
}

View file

@ -99,9 +99,10 @@ android_init_emacs_clipboard (void)
FIND_METHOD (clipboard_exists, "clipboardExists", "()Z");
FIND_METHOD (get_clipboard, "getClipboard", "()[B");
FIND_METHOD (get_clipboard_targets, "getClipboardTargets",
"()[[B");
"()[Ljava/lang/String;");
FIND_METHOD (get_clipboard_data, "getClipboardData",
"([B)Landroid/content/res/AssetFileDescriptor;");
"(Ljava/lang/String;)Landroid/content/res/"
"AssetFileDescriptor;");
clipboard_class.make_clipboard
= (*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
data type available from the clipboard. */)
(void)
{
jarray bytes_array;
jbyteArray bytes;
jarray all_targets;
jstring string;
jmethodID method;
size_t length, length1, i;
jbyte *data;
size_t length, i;
const char *data;
Lisp_Object targets, tem;
if (!android_init_gui)
@ -296,44 +297,42 @@ data type available from the clipboard. */)
targets = Qnil;
block_input ();
method = clipboard_class.get_clipboard_targets;
bytes_array = (*android_java_env)->CallObjectMethod (android_java_env,
all_targets = (*android_java_env)->CallObjectMethod (android_java_env,
clipboard, method);
android_exception_check ();
if (!bytes_array)
if (!all_targets)
goto fail;
length = (*android_java_env)->GetArrayLength (android_java_env,
bytes_array);
all_targets);
for (i = 0; i < length; ++i)
{
/* Retrieve the MIME type. */
bytes
string
= (*android_java_env)->GetObjectArrayElement (android_java_env,
bytes_array, i);
android_exception_check_nonnull (bytes, bytes_array);
all_targets, i);
android_exception_check_nonnull (string, all_targets);
/* Cons it onto the list of targets. */
length1 = (*android_java_env)->GetArrayLength (android_java_env,
bytes);
data = (*android_java_env)->GetByteArrayElements (android_java_env,
bytes, NULL);
android_exception_check_nonnull_1 (data, bytes, bytes_array);
data = (*android_java_env)->GetStringUTFChars (android_java_env,
string, NULL);
android_exception_check_nonnull_1 ((void *) data, string,
all_targets);
/* Decode the string. */
tem = make_unibyte_string ((char *) data, length1);
tem = code_convert_string_norecord (tem, Qutf_8, false);
tem = build_unibyte_string ((char *) data);
tem = code_convert_string_norecord (tem, Qandroid_jni, false);
targets = Fcons (tem, targets);
/* Delete the retrieved data. */
(*android_java_env)->ReleaseByteArrayElements (android_java_env,
bytes, data,
JNI_ABORT);
ANDROID_DELETE_LOCAL_REF (bytes);
(*android_java_env)->ReleaseStringUTFChars (android_java_env,
string, data);
ANDROID_DELETE_LOCAL_REF (string);
}
unblock_input ();
ANDROID_DELETE_LOCAL_REF (bytes_array);
ANDROID_DELETE_LOCAL_REF (all_targets);
return Fnreverse (targets);
fail:
@ -432,7 +431,7 @@ extract_fd_offsets (jobject afd, int *fd, jlong *offset, jlong *length)
#if __ANDROID_API__ <= 11
static int (*jniGetFDFromFileDescriptor) (JNIEnv *, jobject);
#endif /* __ANDROID_API__ <= 11 */
static int (*AFileDescriptor_getFd) (JNIEnv *, jobject);;
static int (*AFileDescriptor_getFd) (JNIEnv *, jobject);
jmethodID method;
method = asset_fd_class.get_start_offset;
@ -538,7 +537,7 @@ does not have any corresponding data. In that case, use
(Lisp_Object type)
{
jobject afd;
jbyteArray bytes;
jstring mime_type;
jmethodID method;
int fd;
ptrdiff_t rc;
@ -549,25 +548,17 @@ does not have any corresponding data. In that case, use
if (!android_init_gui)
error ("No Android display connection!");
/* Encode the string as UTF-8. */
CHECK_STRING (type);
type = ENCODE_UTF_8 (type);
/* Then give it to the selection code. */
/* Convert TYPE into a Java string. */
block_input ();
bytes = (*android_java_env)->NewByteArray (android_java_env,
SBYTES (type));
(*android_java_env)->SetByteArrayRegion (android_java_env, bytes,
0, SBYTES (type),
(jbyte *) SDATA (type));
android_exception_check ();
mime_type = android_build_string (type, NULL);
method = clipboard_class.get_clipboard_data;
afd = (*android_java_env)->CallObjectMethod (android_java_env,
clipboard, method,
bytes);
android_exception_check_1 (bytes);
ANDROID_DELETE_LOCAL_REF (bytes);
mime_type);
android_exception_check_1 (mime_type);
ANDROID_DELETE_LOCAL_REF (mime_type);
if (!afd)
goto fail;
@ -578,7 +569,10 @@ does not have any corresponding data. In that case, use
record_unwind_protect_ptr (close_asset_fd, &afd);
if (extract_fd_offsets (afd, &fd, &offset, &length))
return unbind_to (ref, Qnil);
{
unblock_input ();
return unbind_to (ref, Qnil);
}
unblock_input ();
/* Now begin reading from fd. */