diff options
Diffstat (limited to 'services/core/java/com/android/server/clipboard/ClipboardService.java')
-rw-r--r-- | services/core/java/com/android/server/clipboard/ClipboardService.java | 164 |
1 files changed, 10 insertions, 154 deletions
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 72160c203595..f4e06d377a83 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -52,10 +52,6 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; -import android.system.VmSocketAddress; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; @@ -67,128 +63,9 @@ import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.WindowManagerInternal; -import java.io.FileDescriptor; -import java.io.InterruptedIOException; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; import java.util.HashSet; import java.util.List; - -// The following class is Android Emulator specific. It is used to read and -// write contents of the host system's clipboard. -class HostClipboardMonitor implements Runnable { - public interface HostClipboardCallback { - void onHostClipboardUpdated(String contents); - } - - private FileDescriptor mPipe = null; - private HostClipboardCallback mHostClipboardCallback; - private static final String PIPE_NAME = "pipe:clipboard"; - private static final int HOST_PORT = 5000; - - private static byte[] createOpenHandshake() { - // String.getBytes doesn't include the null terminator, - // but the QEMU pipe device requires the pipe service name - // to be null-terminated. - - final byte[] bits = Arrays.copyOf(PIPE_NAME.getBytes(), PIPE_NAME.length() + 1); - bits[PIPE_NAME.length()] = 0; - return bits; - } - - private boolean openPipe() { - try { - final FileDescriptor fd = Os.socket(OsConstants.AF_VSOCK, OsConstants.SOCK_STREAM, 0); - - try { - Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST)); - - final byte[] handshake = createOpenHandshake(); - Os.write(fd, handshake, 0, handshake.length); - mPipe = fd; - return true; - } catch (ErrnoException | SocketException | InterruptedIOException e) { - Os.close(fd); - } - } catch (ErrnoException e) { - } - - return false; - } - - private void closePipe() { - try { - final FileDescriptor fd = mPipe; - mPipe = null; - if (fd != null) { - Os.close(fd); - } - } catch (ErrnoException ignore) { - } - } - - private byte[] receiveMessage() throws ErrnoException, InterruptedIOException { - final byte[] lengthBits = new byte[4]; - Os.read(mPipe, 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]; - Os.read(mPipe, msg, 0, msg.length); - - return msg; - } - - private void sendMessage(byte[] msg) throws ErrnoException, InterruptedIOException { - final byte[] lengthBits = new byte[4]; - final ByteBuffer bb = ByteBuffer.wrap(lengthBits); - bb.order(ByteOrder.LITTLE_ENDIAN); - bb.putInt(msg.length); - - Os.write(mPipe, lengthBits, 0, lengthBits.length); - Os.write(mPipe, msg, 0, msg.length); - } - - public HostClipboardMonitor(HostClipboardCallback cb) { - mHostClipboardCallback = cb; - } - - @Override - public void run() { - while (!Thread.interrupted()) { - try { - // 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 ((mPipe == null) && !openPipe()) { - Thread.sleep(100); - } - - final byte[] receivedData = receiveMessage(); - mHostClipboardCallback.onHostClipboardUpdated( - new String(receivedData)); - } catch (ErrnoException | InterruptedIOException e) { - closePipe(); - } catch (InterruptedException e) { - } - } - } - - public void setHostClipboard(String content) { - try { - if (mPipe != null) { - sendMessage(content.getBytes()); - } - } catch (ErrnoException | InterruptedIOException e) { - Slog.e("HostClipboardMonitor", - "Failed to set host clipboard " + e.getMessage()); - } - } -} +import java.util.function.Consumer; /** * Implementation of the clipboard for copy and paste. @@ -214,8 +91,7 @@ public class ClipboardService extends SystemService { private final ContentCaptureManagerInternal mContentCaptureInternal; private final AutofillManagerInternal mAutofillInternal; private final IBinder mPermissionOwner; - private HostClipboardMonitor mHostClipboardMonitor = null; - private Thread mHostMonitorThread = null; + private final Consumer<ClipData> mEmulatorClipboardMonitor; private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>(); @@ -237,22 +113,13 @@ public class ClipboardService extends SystemService { final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard"); mPermissionOwner = permOwner; if (IS_EMULATOR) { - mHostClipboardMonitor = new HostClipboardMonitor( - new HostClipboardMonitor.HostClipboardCallback() { - @Override - public void onHostClipboardUpdated(String contents){ - ClipData clip = - new ClipData("host clipboard", - new String[]{"text/plain"}, - new ClipData.Item(contents)); - synchronized(mClipboards) { - setPrimaryClipInternal(getClipboard(0), clip, - android.os.Process.SYSTEM_UID); - } - } - }); - mHostMonitorThread = new Thread(mHostClipboardMonitor); - mHostMonitorThread.start(); + mEmulatorClipboardMonitor = new EmulatorClipboardMonitor((clip) -> { + synchronized (this) { + setPrimaryClipInternal(getClipboard(0), clip, android.os.Process.SYSTEM_UID); + } + }); + } else { + mEmulatorClipboardMonitor = (clip) -> {}; } } @@ -547,18 +414,7 @@ public class ClipboardService extends SystemService { } void setPrimaryClipInternal(@Nullable ClipData clip, int uid) { - // Push clipboard to host, if any - if (mHostClipboardMonitor != null) { - if (clip == null) { - // Someone really wants the clipboard cleared, so push empty - mHostClipboardMonitor.setHostClipboard(""); - } else if (clip.getItemCount() > 0) { - final CharSequence text = clip.getItemAt(0).getText(); - if (text != null) { - mHostClipboardMonitor.setHostClipboard(text.toString()); - } - } - } + mEmulatorClipboardMonitor.accept(clip); // Update this user final int userId = UserHandle.getUserId(uid); |