From 853dd7d2b6cf24076821c1a3bd31c8971bf5dced Mon Sep 17 00:00:00 2001 From: Roman Kiryanov Date: Wed, 11 May 2022 21:57:50 -0700 Subject: [PATCH 1/2] Cleanup in EmulatorClipboardMonitor (3) make more functions static, less places to mess with the global state. Bug: 231345789 Test: presubmit Signed-off-by: Roman Kiryanov Change-Id: I236b039c4fbbbfb519ba1432326bba9a89d008c2 Merged-In: I236b039c4fbbbfb519ba1432326bba9a89d008c2 --- .../clipboard/EmulatorClipboardMonitor.java | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java index 0ccb4554c0574..aa8aad232569f 100644 --- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java +++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java @@ -82,45 +82,31 @@ class EmulatorClipboardMonitor implements Consumer { return null; } - private void openPipe() throws InterruptedException { - FileDescriptor fd = getPipeFD(); + private static FileDescriptor openPipe() throws InterruptedException { + FileDescriptor fd = openPipeImpl(); - if (fd == null) { + // There's no guarantee that QEMU pipes will be ready at the moment + // this method is invoked. We simply try to get the pipe open and + // retry on failure indefinitely. + while (fd == null) { + Thread.sleep(100); fd = openPipeImpl(); - - // There's no guarantee that QEMU pipes will be ready at the moment - // this method is invoked. We simply try to get the pipe open and - // retry on failure indefinitely. - while (fd == null) { - Thread.sleep(100); - fd = openPipeImpl(); - } } - setPipeFD(fd); + return fd; } - private synchronized void closePipe() { - try { - final FileDescriptor fd = mPipe; - mPipe = null; - if (fd != null) { - Os.close(fd); - } - } catch (ErrnoException ignore) { - } - } - - private byte[] receiveMessage() throws ErrnoException, InterruptedIOException, EOFException { + private static byte[] receiveMessage(final FileDescriptor fd) throws ErrnoException, + InterruptedIOException, EOFException { final byte[] lengthBits = new byte[4]; - readFully(mPipe, lengthBits, 0, lengthBits.length); + readFully(fd, lengthBits, 0, lengthBits.length); final ByteBuffer bb = ByteBuffer.wrap(lengthBits); bb.order(ByteOrder.LITTLE_ENDIAN); final int msgLen = bb.getInt(); final byte[] msg = new byte[msgLen]; - readFully(mPipe, msg, 0, msg.length); + readFully(fd, msg, 0, msg.length); return msg; } @@ -139,11 +125,16 @@ class EmulatorClipboardMonitor implements Consumer { EmulatorClipboardMonitor(final Consumer setAndroidClipboard) { this.mHostMonitorThread = new Thread(() -> { + FileDescriptor fd = null; + while (!Thread.interrupted()) { try { - openPipe(); + if (fd == null) { + fd = openPipe(); + setPipeFD(fd); + } - final byte[] receivedData = receiveMessage(); + final byte[] receivedData = receiveMessage(fd); final String str = new String(receivedData); final ClipData clip = new ClipData("host clipboard", @@ -154,9 +145,17 @@ class EmulatorClipboardMonitor implements Consumer { Slog.i(TAG, "Setting the guest clipboard to '" + str + "'"); } setAndroidClipboard.accept(clip); - } catch (ErrnoException | EOFException | InterruptedIOException e) { - closePipe(); - } catch (InterruptedException | IllegalArgumentException e) { + } catch (ErrnoException | EOFException | InterruptedIOException + | InterruptedException e) { + setPipeFD(null); + + try { + Os.close(fd); + } catch (ErrnoException e2) { + // ignore + } + + fd = null; } } }); From 73cc189a3d52d343ba7ef95e604bf4e80a7ca8a7 Mon Sep 17 00:00:00 2001 From: Roman Kiryanov Date: Wed, 11 May 2022 22:22:05 -0700 Subject: [PATCH 2/2] Cleanup in EmulatorClipboardMonitor (4) Bug: 231345789 Test: presubmit Signed-off-by: Roman Kiryanov Change-Id: I9ba57f4347e50f8462cec347e5608ec4d1eb0b30 Merged-In: I9ba57f4347e50f8462cec347e5608ec4d1eb0b30 --- .../clipboard/EmulatorClipboardMonitor.java | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java index aa8aad232569f..46b757cf85d31 100644 --- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java +++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java @@ -165,34 +165,43 @@ class EmulatorClipboardMonitor implements Consumer { @Override public void accept(final @Nullable ClipData clip) { - if (clip == null) { - setHostClipboardImpl(""); - } else if (clip.getItemCount() > 0) { - final CharSequence text = clip.getItemAt(0).getText(); - if (text != null) { - setHostClipboardImpl(text.toString()); - } + final FileDescriptor fd = getPipeFD(); + if (fd != null) { + setHostClipboard(fd, getClipString(clip)); } } - private void setHostClipboardImpl(final String value) { - final FileDescriptor pipeFD = getPipeFD(); - - if (pipeFD != null) { - Thread t = new Thread(() -> { - if (LOG_CLIBOARD_ACCESS) { - Slog.i(TAG, "Setting the host clipboard to '" + value + "'"); - } - - try { - sendMessage(pipeFD, value.getBytes()); - } catch (ErrnoException | InterruptedIOException e) { - Slog.e(TAG, "Failed to set host clipboard " + e.getMessage()); - } catch (IllegalArgumentException e) { - } - }); - t.start(); + private String getClipString(final @Nullable ClipData clip) { + if (clip == null) { + return ""; } + + if (clip.getItemCount() == 0) { + return ""; + } + + final CharSequence text = clip.getItemAt(0).getText(); + if (text == null) { + return ""; + } + + return text.toString(); + } + + private static void setHostClipboard(final FileDescriptor fd, final String value) { + Thread t = new Thread(() -> { + if (LOG_CLIBOARD_ACCESS) { + Slog.i(TAG, "Setting the host clipboard to '" + value + "'"); + } + + try { + sendMessage(fd, value.getBytes()); + } catch (ErrnoException | InterruptedIOException e) { + Slog.e(TAG, "Failed to set host clipboard " + e.getMessage()); + } catch (IllegalArgumentException e) { + } + }); + t.start(); } private static void readFully(final FileDescriptor fd,