Merge changes from topics "presubmit-am-80b91e5f6c3340c785b1772da3a86806", "presubmit-am-8e48e4d2f9da4d69bc62fe6a4b39ef56", "presubmit-am-c978438eb5db452d8793cafc3024df96", "presubmit-am-d09990e2eb2246b1ac4d9766ce468226" into sc-v2-dev
* changes: Cleanup in EmulatorClipboardMonitor (1) Add wrappers around IO functions to check the return values Set host's clipboard in a separate thread Log emulator's clipboard access to logcat
This commit is contained in:
committed by
Android (Google) Code Review
commit
fd5ed2cfd6
@@ -18,12 +18,14 @@ package com.android.server.clipboard;
|
|||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
import android.system.VmSocketAddress;
|
import android.system.VmSocketAddress;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
@@ -39,6 +41,8 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
private static final String PIPE_NAME = "pipe:clipboard";
|
private static final String PIPE_NAME = "pipe:clipboard";
|
||||||
private static final int HOST_PORT = 5000;
|
private static final int HOST_PORT = 5000;
|
||||||
private final Thread mHostMonitorThread;
|
private final Thread mHostMonitorThread;
|
||||||
|
private static final boolean LOG_CLIBOARD_ACCESS =
|
||||||
|
SystemProperties.getBoolean("ro.boot.qemu.log_clipboard_access", false);
|
||||||
private FileDescriptor mPipe = null;
|
private FileDescriptor mPipe = null;
|
||||||
|
|
||||||
private static byte[] createOpenHandshake() {
|
private static byte[] createOpenHandshake() {
|
||||||
@@ -51,8 +55,8 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPipeOpened() {
|
private synchronized FileDescriptor getPipeFD() {
|
||||||
return mPipe != null;
|
return mPipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean openPipe() {
|
private synchronized boolean openPipe() {
|
||||||
@@ -67,7 +71,7 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST));
|
Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST));
|
||||||
|
|
||||||
final byte[] handshake = createOpenHandshake();
|
final byte[] handshake = createOpenHandshake();
|
||||||
Os.write(fd, handshake, 0, handshake.length);
|
writeFully(fd, handshake, 0, handshake.length);
|
||||||
mPipe = fd;
|
mPipe = fd;
|
||||||
return true;
|
return true;
|
||||||
} catch (ErrnoException | SocketException | InterruptedIOException e) {
|
} catch (ErrnoException | SocketException | InterruptedIOException e) {
|
||||||
@@ -90,28 +94,30 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] receiveMessage() throws ErrnoException, InterruptedIOException {
|
private byte[] receiveMessage() throws ErrnoException, InterruptedIOException, EOFException {
|
||||||
final byte[] lengthBits = new byte[4];
|
final byte[] lengthBits = new byte[4];
|
||||||
Os.read(mPipe, lengthBits, 0, lengthBits.length);
|
readFully(mPipe, lengthBits, 0, lengthBits.length);
|
||||||
|
|
||||||
final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
|
final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
|
||||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
final int msgLen = bb.getInt();
|
final int msgLen = bb.getInt();
|
||||||
|
|
||||||
final byte[] msg = new byte[msgLen];
|
final byte[] msg = new byte[msgLen];
|
||||||
Os.read(mPipe, msg, 0, msg.length);
|
readFully(mPipe, msg, 0, msg.length);
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMessage(final byte[] msg) throws ErrnoException, InterruptedIOException {
|
private static void sendMessage(
|
||||||
|
final FileDescriptor fd,
|
||||||
|
final byte[] msg) throws ErrnoException, InterruptedIOException {
|
||||||
final byte[] lengthBits = new byte[4];
|
final byte[] lengthBits = new byte[4];
|
||||||
final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
|
final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
|
||||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
bb.putInt(msg.length);
|
bb.putInt(msg.length);
|
||||||
|
|
||||||
Os.write(mPipe, lengthBits, 0, lengthBits.length);
|
writeFully(fd, lengthBits, 0, lengthBits.length);
|
||||||
Os.write(mPipe, msg, 0, msg.length);
|
writeFully(fd, msg, 0, msg.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulatorClipboardMonitor(final Consumer<ClipData> setAndroidClipboard) {
|
EmulatorClipboardMonitor(final Consumer<ClipData> setAndroidClipboard) {
|
||||||
@@ -132,8 +138,11 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
new String[]{"text/plain"},
|
new String[]{"text/plain"},
|
||||||
new ClipData.Item(str));
|
new ClipData.Item(str));
|
||||||
|
|
||||||
|
if (LOG_CLIBOARD_ACCESS) {
|
||||||
|
Slog.i(TAG, "Setting the guest clipboard to '" + str + "'");
|
||||||
|
}
|
||||||
setAndroidClipboard.accept(clip);
|
setAndroidClipboard.accept(clip);
|
||||||
} catch (ErrnoException | InterruptedIOException e) {
|
} catch (ErrnoException | EOFException | InterruptedIOException e) {
|
||||||
closePipe();
|
closePipe();
|
||||||
} catch (InterruptedException | IllegalArgumentException e) {
|
} catch (InterruptedException | IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
@@ -156,13 +165,50 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setHostClipboardImpl(final String value) {
|
private void setHostClipboardImpl(final String value) {
|
||||||
try {
|
final FileDescriptor pipeFD = getPipeFD();
|
||||||
if (isPipeOpened()) {
|
|
||||||
sendMessage(value.getBytes());
|
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 static void readFully(final FileDescriptor fd,
|
||||||
|
final byte[] buf, int offset, int size)
|
||||||
|
throws ErrnoException, InterruptedIOException, EOFException {
|
||||||
|
while (size > 0) {
|
||||||
|
final int r = Os.read(fd, buf, offset, size);
|
||||||
|
if (r > 0) {
|
||||||
|
offset += r;
|
||||||
|
size -= r;
|
||||||
|
} else {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeFully(final FileDescriptor fd,
|
||||||
|
final byte[] buf, int offset, int size)
|
||||||
|
throws ErrnoException, InterruptedIOException {
|
||||||
|
while (size > 0) {
|
||||||
|
final int r = Os.write(fd, buf, offset, size);
|
||||||
|
if (r > 0) {
|
||||||
|
offset += r;
|
||||||
|
size -= r;
|
||||||
|
} else {
|
||||||
|
throw new ErrnoException("write", OsConstants.EIO);
|
||||||
}
|
}
|
||||||
} catch (ErrnoException | InterruptedIOException e) {
|
|
||||||
Slog.e(TAG, "Failed to set host clipboard " + e.getMessage());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user