Browse Source

Removing local copy of adblib code

Anwar Mohammad Abdul 4 năm trước cách đây
mục cha
commit
b288eb7db7

+ 0 - 18
app/src/main/java/org/las2mile/scrcpy/adblib/AdbBase64.java

@@ -1,18 +0,0 @@
-package org.las2mile.scrcpy.adblib;
-
-/**
- * This interface specifies the required functions for AdbCrypto to
- * perform Base64 encoding of its public key.
- *
- * @author Cameron Gutman
- */
-public interface AdbBase64 {
-    /**
-     * This function must encoded the specified data as a base 64 string, without
-     * appending any extra newlines or other characters.
-     *
-     * @param data Data to encode
-     * @return String containing base 64 encoded data
-     */
-    public String encodeToString(byte[] data);
-}

+ 0 - 364
app/src/main/java/org/las2mile/scrcpy/adblib/AdbConnection.java

@@ -1,364 +0,0 @@
-package org.las2mile.scrcpy.adblib;
-
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.ConnectException;
-import java.net.Socket;
-import java.util.HashMap;
-
-/**
- * This class represents an ADB connection.
- *
- * @author Cameron Gutman
- */
-public class AdbConnection implements Closeable {
-
-    /**
-     * The output stream that this class uses to read from
-     * the socket.
-     */
-    OutputStream outputStream;
-    /**
-     * The underlying socket that this class uses to
-     * communicate with the target device.
-     */
-    private Socket socket;
-    /**
-     * The last allocated local stream ID. The ID
-     * chosen for the next stream will be this value + 1.
-     */
-    private int lastLocalId;
-    /**
-     * The input stream that this class uses to read from
-     * the socket.
-     */
-    private InputStream inputStream;
-    /**
-     * The backend thread that handles responding to ADB packets.
-     */
-    private Thread connectionThread;
-
-    /**
-     * Specifies whether a connect has been attempted
-     */
-    private boolean connectAttempted;
-
-    /**
-     * Specifies whether a CNXN packet has been received from the peer.
-     */
-    private boolean connected;
-
-    /**
-     * Specifies the maximum amount data that can be sent to the remote peer.
-     * This is only valid after connect() returns successfully.
-     */
-    private int maxData;
-
-    /**
-     * An initialized ADB crypto object that contains a key pair.
-     */
-    private AdbCrypto crypto;
-
-    /**
-     * Specifies whether this connection has already sent a signed token.
-     */
-    private boolean sentSignature;
-
-    /**
-     * A hash map of our open streams indexed by local ID.
-     **/
-    private HashMap<Integer, AdbStream> openStreams;
-
-    /**
-     * Internal constructor to initialize some internal state
-     */
-    private AdbConnection() {
-        openStreams = new HashMap<Integer, AdbStream>();
-        lastLocalId = 0;
-        connectionThread = createConnectionThread();
-    }
-
-    /**
-     * Creates a AdbConnection object associated with the socket and
-     * crypto object specified.
-     *
-     * @param socket The socket that the connection will use for communcation.
-     * @param crypto The crypto object that stores the key pair for authentication.
-     * @return A new AdbConnection object.
-     * @throws IOException If there is a socket error
-     */
-    public static AdbConnection create(Socket socket, AdbCrypto crypto) throws IOException {
-        AdbConnection newConn = new AdbConnection();
-
-        newConn.crypto = crypto;
-
-        newConn.socket = socket;
-        newConn.inputStream = socket.getInputStream();
-        newConn.outputStream = socket.getOutputStream();
-
-        /* Disable Nagle because we're sending tiny packets */
-        socket.setTcpNoDelay(true);
-
-        return newConn;
-    }
-
-    /**
-     * Creates a new connection thread.
-     *
-     * @return A new connection thread.
-     */
-    private Thread createConnectionThread() {
-        @SuppressWarnings("resource") final AdbConnection conn = this;
-        return new Thread(new Runnable() {
-            @Override
-            public void run() {
-                while (!connectionThread.isInterrupted()) {
-                    try {
-                        /* Read and parse a message off the socket's input stream */
-                        AdbProtocol.AdbMessage msg = AdbProtocol.AdbMessage.parseAdbMessage(inputStream);
-
-                        /* Verify magic and checksum */
-                        if (!AdbProtocol.validateMessage(msg))
-                            continue;
-
-                        switch (msg.command) {
-                            /* Stream-oriented commands */
-                            case AdbProtocol.CMD_OKAY:
-                            case AdbProtocol.CMD_WRTE:
-                            case AdbProtocol.CMD_CLSE:
-                                /* We must ignore all packets when not connected */
-                                if (!conn.connected)
-                                    continue;
-
-                                /* Get the stream object corresponding to the packet */
-                                AdbStream waitingStream = openStreams.get(msg.arg1);
-                                if (waitingStream == null)
-                                    continue;
-
-                                synchronized (waitingStream) {
-                                    if (msg.command == AdbProtocol.CMD_OKAY) {
-                                        /* We're ready for writes */
-                                        waitingStream.updateRemoteId(msg.arg0);
-                                        waitingStream.readyForWrite();
-
-                                        /* Unwait an open/write */
-                                        waitingStream.notify();
-                                    } else if (msg.command == AdbProtocol.CMD_WRTE) {
-                                        /* Got some data from our partner */
-                                        waitingStream.addPayload(msg.payload);
-
-                                        /* Tell it we're ready for more */
-                                        waitingStream.sendReady();
-                                    } else if (msg.command == AdbProtocol.CMD_CLSE) {
-                                        /* He doesn't like us anymore :-( */
-                                        conn.openStreams.remove(msg.arg1);
-
-                                        /* Notify readers and writers */
-                                        waitingStream.notifyClose();
-                                    }
-                                }
-
-                                break;
-
-                            case AdbProtocol.CMD_AUTH:
-
-                                byte[] packet;
-
-                                if (msg.arg0 == AdbProtocol.AUTH_TYPE_TOKEN) {
-                                    /* This is an authentication challenge */
-                                    if (conn.sentSignature) {
-                                        /* We've already tried our signature, so send our public key */
-                                        packet = AdbProtocol.generateAuth(AdbProtocol.AUTH_TYPE_RSA_PUBLIC,
-                                                conn.crypto.getAdbPublicKeyPayload());
-                                    } else {
-                                        /* We'll sign the token */
-                                        packet = AdbProtocol.generateAuth(AdbProtocol.AUTH_TYPE_SIGNATURE,
-                                                conn.crypto.signAdbTokenPayload(msg.payload));
-                                        conn.sentSignature = true;
-                                    }
-
-                                    /* Write the AUTH reply */
-                                    conn.outputStream.write(packet);
-                                    conn.outputStream.flush();
-                                }
-                                break;
-
-                            case AdbProtocol.CMD_CNXN:
-                                synchronized (conn) {
-                                    /* We need to store the max data size */
-                                    conn.maxData = msg.arg1;
-
-                                    /* Mark us as connected and unwait anyone waiting on the connection */
-                                    conn.connected = true;
-                                    conn.notifyAll();
-                                }
-                                break;
-
-                            default:
-                                /* Unrecognized packet, just drop it */
-                                break;
-                        }
-                    } catch (Exception e) {
-                        /* The cleanup is taken care of by a combination of this thread
-                         * and close() */
-                        break;
-                    }
-                }
-
-                /* This thread takes care of cleaning up pending streams */
-                synchronized (conn) {
-                    cleanupStreams();
-                    conn.notifyAll();
-                    conn.connectAttempted = false;
-                }
-            }
-        });
-    }
-
-    /**
-     * Gets the max data size that the remote client supports.
-     * A connection must have been attempted before calling this routine.
-     * This routine will block if a connection is in progress.
-     *
-     * @return The maximum data size indicated in the connect packet.
-     * @throws InterruptedException If a connection cannot be waited on.
-     * @throws IOException          if the connection fails
-     */
-    public int getMaxData() throws InterruptedException, IOException {
-        if (!connectAttempted)
-            throw new IllegalStateException("connect() must be called first");
-
-        synchronized (this) {
-            /* Block if a connection is pending, but not yet complete */
-            if (!connected)
-                wait();
-
-            if (!connected) {
-                throw new IOException("Connection failed");
-            }
-        }
-
-        return maxData;
-    }
-
-    /**
-     * Connects to the remote device. This routine will block until the connection
-     * completes.
-     *
-     * @throws IOException          If the socket fails while connecting
-     * @throws InterruptedException If we are unable to wait for the connection to finish
-     */
-    public void connect() throws IOException, InterruptedException {
-        if (connected)
-            throw new IllegalStateException("Already connected");
-
-        /* Write the CONNECT packet */
-        outputStream.write(AdbProtocol.generateConnect());
-        outputStream.flush();
-
-        /* Start the connection thread to respond to the peer */
-        connectAttempted = true;
-        connectionThread.start();
-
-        /* Wait for the connection to go live */
-        synchronized (this) {
-            if (!connected)
-                wait();
-
-            if (!connected) {
-                throw new IOException("Connection failed");
-            }
-        }
-    }
-
-    /**
-     * Opens an AdbStream object corresponding to the specified destination.
-     * This routine will block until the connection completes.
-     *
-     * @param destination The destination to open on the target
-     * @return AdbStream object corresponding to the specified destination
-     * @throws UnsupportedEncodingException If the destination cannot be encoded to UTF-8
-     * @throws IOException                  If the stream fails while sending the packet
-     * @throws InterruptedException         If we are unable to wait for the connection to finish
-     */
-    public AdbStream open(String destination) throws UnsupportedEncodingException, IOException, InterruptedException {
-        int localId = ++lastLocalId;
-
-        if (!connectAttempted)
-            throw new IllegalStateException("connect() must be called first");
-
-        /* Wait for the connect response */
-        synchronized (this) {
-            if (!connected)
-                wait();
-
-            if (!connected) {
-                throw new IOException("Connection failed");
-            }
-        }
-
-        /* Add this stream to this list of half-open streams */
-        AdbStream stream = new AdbStream(this, localId);
-        openStreams.put(localId, stream);
-
-        /* Send the open */
-        outputStream.write(AdbProtocol.generateOpen(localId, destination));
-        outputStream.flush();
-
-        /* Wait for the connection thread to receive the OKAY */
-        synchronized (stream) {
-            stream.wait();
-        }
-
-        /* Check if the open was rejected */
-        if (stream.isClosed())
-            throw new ConnectException("Stream open actively rejected by remote peer");
-
-        /* We're fully setup now */
-        return stream;
-    }
-
-    /**
-     * This function terminates all I/O on streams associated with this ADB connection
-     */
-    private void cleanupStreams() {
-        /* Close all streams on this connection */
-        for (AdbStream s : openStreams.values()) {
-            /* We handle exceptions for each close() call to avoid
-             * terminating cleanup for one failed close(). */
-            try {
-                s.close();
-            } catch (IOException e) {
-            }
-        }
-
-        /* No open streams anymore */
-        openStreams.clear();
-    }
-
-    /**
-     * This routine closes the Adb connection and underlying socket
-     *
-     * @throws IOException if the socket fails to close
-     */
-    @Override
-    public void close() throws IOException {
-        /* If the connection thread hasn't spawned yet, there's nothing to do */
-        if (connectionThread == null)
-            return;
-
-        /* Closing the socket will kick the connection thread */
-        socket.close();
-
-        /* Wait for the connection thread to die */
-        connectionThread.interrupt();
-        try {
-            connectionThread.join();
-        } catch (InterruptedException e) {
-        }
-    }
-}

+ 0 - 236
app/src/main/java/org/las2mile/scrcpy/adblib/AdbCrypto.java

@@ -1,236 +0,0 @@
-package org.las2mile.scrcpy.adblib;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.EncodedKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.Cipher;
-
-/**
- * This class encapsulates the ADB cryptography functions and provides
- * an interface for the storage and retrieval of keys.
- *
- * @author Cameron Gutman
- */
-public class AdbCrypto {
-
-    /**
-     * The ADB RSA key length in bits
-     */
-    public static final int KEY_LENGTH_BITS = 2048;
-    /**
-     * The ADB RSA key length in bytes
-     */
-    public static final int KEY_LENGTH_BYTES = KEY_LENGTH_BITS / 8;
-    /**
-     * The ADB RSA key length in words
-     */
-    public static final int KEY_LENGTH_WORDS = KEY_LENGTH_BYTES / 4;
-    /**
-     * The RSA signature padding as an int array
-     */
-    public static final int[] SIGNATURE_PADDING_AS_INT = new int[]
-            {
-                    0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-                    0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00,
-                    0x04, 0x14
-            };
-    /**
-     * The RSA signature padding as a byte array
-     */
-    public static byte[] SIGNATURE_PADDING;
-
-    static {
-        SIGNATURE_PADDING = new byte[SIGNATURE_PADDING_AS_INT.length];
-
-        for (int i = 0; i < SIGNATURE_PADDING.length; i++)
-            SIGNATURE_PADDING[i] = (byte) SIGNATURE_PADDING_AS_INT[i];
-    }
-
-    /**
-     * An RSA keypair encapsulated by the AdbCrypto object
-     */
-    private KeyPair keyPair;
-    /**
-     * The base 64 conversion interface to use
-     */
-    private AdbBase64 base64;
-
-    /**
-     * Converts a standard RSAPublicKey object to the special ADB format
-     *
-     * @param pubkey RSAPublicKey object to convert
-     * @return Byte array containing the converted RSAPublicKey object
-     */
-    private static byte[] convertRsaPublicKeyToAdbFormat(RSAPublicKey pubkey) {
-        /*
-         * ADB literally just saves the RSAPublicKey struct to a file.
-         *
-         * typedef struct RSAPublicKey {
-         * int len; // Length of n[] in number of uint32_t
-         * uint32_t n0inv;  // -1 / n[0] mod 2^32
-         * uint32_t n[RSANUMWORDS]; // modulus as little endian array
-         * uint32_t rr[RSANUMWORDS]; // R^2 as little endian array
-         * int exponent; // 3 or 65537
-         * } RSAPublicKey;
-         */
-
-        /* ------ This part is a Java-ified version of RSA_to_RSAPublicKey from adb_host_auth.c ------ */
-        BigInteger r32, r, rr, rem, n, n0inv;
-
-        r32 = BigInteger.ZERO.setBit(32);
-        n = pubkey.getModulus();
-        r = BigInteger.ZERO.setBit(KEY_LENGTH_WORDS * 32);
-        rr = r.modPow(BigInteger.valueOf(2), n);
-        rem = n.remainder(r32);
-        n0inv = rem.modInverse(r32);
-
-        int myN[] = new int[KEY_LENGTH_WORDS];
-        int myRr[] = new int[KEY_LENGTH_WORDS];
-        BigInteger res[];
-        for (int i = 0; i < KEY_LENGTH_WORDS; i++) {
-            res = rr.divideAndRemainder(r32);
-            rr = res[0];
-            rem = res[1];
-            myRr[i] = rem.intValue();
-
-            res = n.divideAndRemainder(r32);
-            n = res[0];
-            rem = res[1];
-            myN[i] = rem.intValue();
-        }
-
-        /* ------------------------------------------------------------------------------------------- */
-
-        ByteBuffer bbuf = ByteBuffer.allocate(524).order(ByteOrder.LITTLE_ENDIAN);
-
-
-        bbuf.putInt(KEY_LENGTH_WORDS);
-        bbuf.putInt(n0inv.negate().intValue());
-        for (int i : myN)
-            bbuf.putInt(i);
-        for (int i : myRr)
-            bbuf.putInt(i);
-
-        bbuf.putInt(pubkey.getPublicExponent().intValue());
-        return bbuf.array();
-    }
-
-
-    public static AdbCrypto loadAdbKeyPair(AdbBase64 base64, FileInputStream privIn, FileInputStream pubIn) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
-        AdbCrypto crypto = new AdbCrypto();
-
-        byte[] privKeyBytes = new byte[privIn.available()];
-        byte[] pubKeyBytes = new byte[pubIn.available()];
-
-        privIn.read(privKeyBytes);
-        pubIn.read(pubKeyBytes);
-
-        privIn.close();
-        pubIn.close();
-
-        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
-        EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyBytes);
-        EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pubKeyBytes);
-
-        crypto.keyPair = new KeyPair(keyFactory.generatePublic(publicKeySpec),
-                keyFactory.generatePrivate(privateKeySpec));
-        crypto.base64 = base64;
-
-        return crypto;
-    }
-
-
-    /**
-     * Creates a new AdbCrypto object by generating a new key pair.
-     *
-     * @param base64 Implementation of base 64 conversion interface required by ADB
-     * @return A new AdbCrypto object
-     * @throws NoSuchAlgorithmException If an RSA key factory cannot be found
-     */
-    public static AdbCrypto generateAdbKeyPair(AdbBase64 base64) throws NoSuchAlgorithmException {
-        AdbCrypto crypto = new AdbCrypto();
-
-        KeyPairGenerator rsaKeyPg = KeyPairGenerator.getInstance("RSA");
-        rsaKeyPg.initialize(KEY_LENGTH_BITS);
-
-        crypto.keyPair = rsaKeyPg.genKeyPair();
-        crypto.base64 = base64;
-
-        return crypto;
-    }
-
-    /**
-     * Signs the ADB SHA1 payload with the private key of this object.
-     *
-     * @param payload SHA1 payload to sign
-     * @return Signed SHA1 payload
-     * @throws GeneralSecurityException If signing fails
-     */
-    public byte[] signAdbTokenPayload(byte[] payload) throws GeneralSecurityException {
-        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding");
-
-        c.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
-
-        c.update(SIGNATURE_PADDING);
-
-        return c.doFinal(payload);
-    }
-
-    /**
-     * Gets the RSA public key in ADB format.
-     *
-     * @return Byte array containing the RSA public key in ADB format.
-     * @throws IOException If the key cannot be retrived
-     */
-    public byte[] getAdbPublicKeyPayload() throws IOException {
-        byte[] convertedKey = convertRsaPublicKeyToAdbFormat((RSAPublicKey) keyPair.getPublic());
-        StringBuilder keyString = new StringBuilder(720);
-
-        /* The key is base64 encoded with a user@host suffix and terminated with a NUL */
-        keyString.append(base64.encodeToString(convertedKey));
-        keyString.append(" unknown@unknown");
-        keyString.append('\0');
-
-        return keyString.toString().getBytes("UTF-8");
-    }
-
-
-    public void saveAdbKeyPair(FileOutputStream privOut, FileOutputStream pubOut) throws IOException {
-
-        privOut.write(keyPair.getPrivate().getEncoded());
-        pubOut.write(keyPair.getPublic().getEncoded());
-
-        privOut.close();
-        pubOut.close();
-    }
-}

+ 0 - 333
app/src/main/java/org/las2mile/scrcpy/adblib/AdbProtocol.java

@@ -1,333 +0,0 @@
-package org.las2mile.scrcpy.adblib;
-
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * This class provides useful functions and fields for ADB protocol details.
- *
- * @author Cameron Gutman
- */
-public class AdbProtocol {
-
-    /**
-     * The length of the ADB message header
-     */
-    public static final int ADB_HEADER_LENGTH = 24;
-
-    public static final int CMD_SYNC = 0x434e5953;
-
-    /**
-     * CNXN is the connect message. No messages (except AUTH)
-     * are valid before this message is received.
-     */
-    public static final int CMD_CNXN = 0x4e584e43;
-
-    /**
-     * The current version of the ADB protocol
-     */
-    public static final int CONNECT_VERSION = 0x01000000;
-
-    /**
-     * The maximum data payload supported by the ADB implementation
-     */
-    public static final int CONNECT_MAXDATA = 4096;
-    /**
-     * AUTH is the authentication message. It is part of the
-     * RSA public key authentication added in Android 4.2.2.
-     */
-    public static final int CMD_AUTH = 0x48545541;
-    /**
-     * This authentication type represents a SHA1 hash to sign
-     */
-    public static final int AUTH_TYPE_TOKEN = 1;
-    /**
-     * This authentication type represents the signed SHA1 hash
-     */
-    public static final int AUTH_TYPE_SIGNATURE = 2;
-    /**
-     * This authentication type represents a RSA public key
-     */
-    public static final int AUTH_TYPE_RSA_PUBLIC = 3;
-    /**
-     * OPEN is the open stream message. It is sent to open
-     * a new stream on the target device.
-     */
-    public static final int CMD_OPEN = 0x4e45504f;
-    /**
-     * OKAY is a success message. It is sent when a write is
-     * processed successfully.
-     */
-    public static final int CMD_OKAY = 0x59414b4f;
-    /**
-     * CLSE is the close stream message. It it sent to close an
-     * existing stream on the target device.
-     */
-    public static final int CMD_CLSE = 0x45534c43;
-    /**
-     * WRTE is the write stream message. It is sent with a payload
-     * that is the data to write to the stream.
-     */
-    public static final int CMD_WRTE = 0x45545257;
-    /**
-     * The payload sent with the connect message
-     */
-    public static byte[] CONNECT_PAYLOAD;
-
-    static {
-        try {
-            CONNECT_PAYLOAD = "host::\0".getBytes("UTF-8");
-        } catch (UnsupportedEncodingException e) {
-        }
-    }
-
-    /**
-     * This function performs a checksum on the ADB payload data.
-     *
-     * @param payload Payload to checksum
-     * @return The checksum of the payload
-     */
-    private static int getPayloadChecksum(byte[] payload) {
-        int checksum = 0;
-
-        for (byte b : payload) {
-            /* We have to manually "unsign" these bytes because Java sucks */
-            if (b >= 0)
-                checksum += b;
-            else
-                checksum += b + 256;
-        }
-
-        return checksum;
-    }
-
-    /**
-     * This function validate the ADB message by checking
-     * its command, magic, and payload checksum.
-     *
-     * @param msg ADB message to validate
-     * @return True if the message was valid, false otherwise
-     */
-    public static boolean validateMessage(AdbMessage msg) {
-        /* Magic is cmd ^ 0xFFFFFFFF */
-        if (msg.command != (msg.magic ^ 0xFFFFFFFF))
-            return false;
-
-        if (msg.payloadLength != 0) {
-            if (getPayloadChecksum(msg.payload) != msg.checksum)
-                return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * This function generates an ADB message given the fields.
-     *
-     * @param cmd     Command identifier
-     * @param arg0    First argument
-     * @param arg1    Second argument
-     * @param payload Data payload
-     * @return Byte array containing the message
-     */
-    public static byte[] generateMessage(int cmd, int arg0, int arg1, byte[] payload) {
-        /* struct message {
-         * 		unsigned command;       // command identifier constant
-         * 		unsigned arg0;          // first argument
-         * 		unsigned arg1;          // second argument
-         * 		unsigned data_length;   // length of payload (0 is allowed)
-         * 		unsigned data_check;    // checksum of data payload
-         * 		unsigned magic;         // command ^ 0xffffffff
-         * };
-         */
-
-        ByteBuffer message;
-
-        if (payload != null) {
-            message = ByteBuffer.allocate(ADB_HEADER_LENGTH + payload.length).order(ByteOrder.LITTLE_ENDIAN);
-        } else {
-            message = ByteBuffer.allocate(ADB_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
-        }
-
-        message.putInt(cmd);
-        message.putInt(arg0);
-        message.putInt(arg1);
-
-        if (payload != null) {
-            message.putInt(payload.length);
-            message.putInt(getPayloadChecksum(payload));
-        } else {
-            message.putInt(0);
-            message.putInt(0);
-        }
-
-        message.putInt(cmd ^ 0xFFFFFFFF);
-
-        if (payload != null) {
-            message.put(payload);
-        }
-
-        return message.array();
-    }
-
-    /**
-     * Generates a connect message with default parameters.
-     *
-     * @return Byte array containing the message
-     */
-    public static byte[] generateConnect() {
-        return generateMessage(CMD_CNXN, CONNECT_VERSION, CONNECT_MAXDATA, CONNECT_PAYLOAD);
-    }
-
-    /**
-     * Generates an auth message with the specified type and payload.
-     *
-     * @param type Authentication type (see AUTH_TYPE_* constants)
-     * @param data The payload for the message
-     * @return Byte array containing the message
-     */
-    public static byte[] generateAuth(int type, byte[] data) {
-        return generateMessage(CMD_AUTH, type, 0, data);
-    }
-
-    /**
-     * Generates an open stream message with the specified local ID and destination.
-     *
-     * @param localId A unique local ID identifying the stream
-     * @param dest    The destination of the stream on the target
-     * @return Byte array containing the message
-     * @throws UnsupportedEncodingException If the destination cannot be encoded to UTF-8
-     */
-    public static byte[] generateOpen(int localId, String dest) throws UnsupportedEncodingException {
-        ByteBuffer bbuf = ByteBuffer.allocate(dest.length() + 1);
-        bbuf.put(dest.getBytes("UTF-8"));
-        bbuf.put((byte) 0);
-        return generateMessage(CMD_OPEN, localId, 0, bbuf.array());
-    }
-
-    /**
-     * Generates a write stream message with the specified IDs and payload.
-     *
-     * @param localId  The unique local ID of the stream
-     * @param remoteId The unique remote ID of the stream
-     * @param data     The data to provide as the write payload
-     * @return Byte array containing the message
-     */
-    public static byte[] generateWrite(int localId, int remoteId, byte[] data) {
-        return generateMessage(CMD_WRTE, localId, remoteId, data);
-    }
-
-    /**
-     * Generates a close stream message with the specified IDs.
-     *
-     * @param localId  The unique local ID of the stream
-     * @param remoteId The unique remote ID of the stream
-     * @return Byte array containing the message
-     */
-    public static byte[] generateClose(int localId, int remoteId) {
-        return generateMessage(CMD_CLSE, localId, remoteId, null);
-    }
-
-    /**
-     * Generates an okay message with the specified IDs.
-     *
-     * @param localId  The unique local ID of the stream
-     * @param remoteId The unique remote ID of the stream
-     * @return Byte array containing the message
-     */
-    public static byte[] generateReady(int localId, int remoteId) {
-        return generateMessage(CMD_OKAY, localId, remoteId, null);
-    }
-
-    /**
-     * This class provides an abstraction for the ADB message format.
-     *
-     * @author Cameron Gutman
-     */
-    final static class AdbMessage {
-        /**
-         * The command field of the message
-         */
-        public int command;
-        /**
-         * The arg0 field of the message
-         */
-        public int arg0;
-        /**
-         * The arg1 field of the message
-         */
-        public int arg1;
-        /**
-         * The payload length field of the message
-         */
-        public int payloadLength;
-        /**
-         * The checksum field of the message
-         */
-        public int checksum;
-        /**
-         * The magic field of the message
-         */
-        public int magic;
-        /**
-         * The payload of the message
-         */
-        public byte[] payload;
-
-        /**
-         * Read and parse an ADB message from the supplied input stream.
-         * This message is NOT validated.
-         *
-         * @param in InputStream object to read data from
-         * @return An AdbMessage object represented the message read
-         * @throws IOException If the stream fails while reading
-         */
-        public static AdbMessage parseAdbMessage(InputStream in) throws IOException {
-            AdbMessage msg = new AdbMessage();
-            ByteBuffer packet = ByteBuffer.allocate(ADB_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
-
-            /* Read the header first */
-            int dataRead = 0;
-            do {
-                int bytesRead = in.read(packet.array(), dataRead, 24 - dataRead);
-
-                if (bytesRead < 0)
-                    throw new IOException("Stream closed");
-                else
-                    dataRead += bytesRead;
-            }
-            while (dataRead < ADB_HEADER_LENGTH);
-
-            /* Pull out header fields */
-            msg.command = packet.getInt();
-            msg.arg0 = packet.getInt();
-            msg.arg1 = packet.getInt();
-            msg.payloadLength = packet.getInt();
-            msg.checksum = packet.getInt();
-            msg.magic = packet.getInt();
-
-            /* If there's a payload supplied, read that too */
-            if (msg.payloadLength != 0) {
-                msg.payload = new byte[msg.payloadLength];
-
-                dataRead = 0;
-                do {
-                    int bytesRead = in.read(msg.payload, dataRead, msg.payloadLength - dataRead);
-
-                    if (bytesRead < 0)
-                        throw new IOException("Stream closed");
-                    else
-                        dataRead += bytesRead;
-                }
-                while (dataRead < msg.payloadLength);
-            }
-
-            return msg;
-        }
-    }
-}

+ 0 - 222
app/src/main/java/org/las2mile/scrcpy/adblib/AdbStream.java

@@ -1,222 +0,0 @@
-package org.las2mile.scrcpy.adblib;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * This class abstracts the underlying ADB streams
- *
- * @author Cameron Gutman
- */
-public class AdbStream implements Closeable {
-
-    /**
-     * The AdbConnection object that the stream communicates over
-     */
-    private AdbConnection adbConn;
-
-    /**
-     * The local ID of the stream
-     */
-    private int localId;
-
-    /**
-     * The remote ID of the stream
-     */
-    private int remoteId;
-
-    /**
-     * Indicates whether a write is currently allowed
-     */
-    private AtomicBoolean writeReady;
-
-    /**
-     * A queue of data from the target's write packets
-     */
-    private Queue<byte[]> readQueue;
-
-    /**
-     * Indicates whether the connection is closed already
-     */
-    private boolean isClosed;
-
-    /**
-     * Creates a new AdbStream object on the specified AdbConnection
-     * with the given local ID.
-     *
-     * @param adbConn AdbConnection that this stream is running on
-     * @param localId Local ID of the stream
-     */
-    public AdbStream(AdbConnection adbConn, int localId) {
-        this.adbConn = adbConn;
-        this.localId = localId;
-        this.readQueue = new ConcurrentLinkedQueue<byte[]>();
-        this.writeReady = new AtomicBoolean(false);
-        this.isClosed = false;
-    }
-
-    /**
-     * Called by the connection thread to indicate newly received data.
-     *
-     * @param payload Data inside the write message
-     */
-    void addPayload(byte[] payload) {
-        synchronized (readQueue) {
-            readQueue.add(payload);
-            readQueue.notifyAll();
-        }
-    }
-
-    /**
-     * Called by the connection thread to send an OKAY packet, allowing the
-     * other side to continue transmission.
-     *
-     * @throws IOException If the connection fails while sending the packet
-     */
-    void sendReady() throws IOException {
-        /* Generate and send a READY packet */
-        byte[] packet = AdbProtocol.generateReady(localId, remoteId);
-        adbConn.outputStream.write(packet);
-        adbConn.outputStream.flush();
-    }
-
-    /**
-     * Called by the connection thread to update the remote ID for this stream
-     *
-     * @param remoteId New remote ID
-     */
-    void updateRemoteId(int remoteId) {
-        this.remoteId = remoteId;
-    }
-
-    /**
-     * Called by the connection thread to indicate the stream is okay to send data.
-     */
-    void readyForWrite() {
-        writeReady.set(true);
-    }
-
-    /**
-     * Called by the connection thread to notify that the stream was closed by the peer.
-     */
-    void notifyClose() {
-        /* We don't call close() because it sends another CLOSE */
-        isClosed = true;
-
-        /* Unwait readers and writers */
-        synchronized (this) {
-            notifyAll();
-        }
-        synchronized (readQueue) {
-            readQueue.notifyAll();
-        }
-    }
-
-    /**
-     * Reads a pending write payload from the other side.
-     *
-     * @return Byte array containing the payload of the write
-     * @throws InterruptedException If we are unable to wait for data
-     * @throws IOException          If the stream fails while waiting
-     */
-    public byte[] read() throws InterruptedException, IOException {
-        byte[] data = null;
-
-        synchronized (readQueue) {
-            /* Wait for the connection to close or data to be received */
-            while (!isClosed && (data = readQueue.poll()) == null) {
-                readQueue.wait();
-            }
-
-            if (isClosed) {
-                throw new IOException("Stream closed");
-            }
-        }
-
-        return data;
-    }
-
-    /**
-     * Sends a write packet with a given String payload.
-     *
-     * @param payload Payload in the form of a String
-     * @throws IOException          If the stream fails while sending data
-     * @throws InterruptedException If we are unable to wait to send data
-     */
-    public void write(String payload) throws IOException, InterruptedException {
-        /* ADB needs null-terminated strings */
-        write(payload.getBytes("UTF-8"), false);
-        write(new byte[]{0}, true);
-    }
-
-    /**
-     * Sends a write packet with a given byte array payload.
-     *
-     * @param payload Payload in the form of a byte array
-     * @throws IOException          If the stream fails while sending data
-     * @throws InterruptedException If we are unable to wait to send data
-     */
-    public void write(byte[] payload) throws IOException, InterruptedException {
-        write(payload, true);
-    }
-
-    /**
-     * Queues a write packet and optionally sends it immediately.
-     *
-     * @param payload Payload in the form of a byte array
-     * @param flush   Specifies whether to send the packet immediately
-     * @throws IOException          If the stream fails while sending data
-     * @throws InterruptedException If we are unable to wait to send data
-     */
-    public void write(byte[] payload, boolean flush) throws IOException, InterruptedException {
-        synchronized (this) {
-            /* Make sure we're ready for a write */
-            while (!isClosed && !writeReady.compareAndSet(true, false))
-                wait();
-
-            if (isClosed) {
-                throw new IOException("Stream closed");
-            }
-        }
-
-        /* Generate a WRITE packet and send it */
-        byte[] packet = AdbProtocol.generateWrite(localId, remoteId, payload);
-        adbConn.outputStream.write(packet);
-
-        if (flush)
-            adbConn.outputStream.flush();
-    }
-
-    /**
-     * Closes the stream. This sends a close message to the peer.
-     *
-     * @throws IOException If the stream fails while sending the close message.
-     */
-    @Override
-    public void close() throws IOException {
-        synchronized (this) {
-            /* This may already be closed by the remote host */
-            if (isClosed)
-                return;
-
-            /* Notify readers/writers that we've closed */
-            notifyClose();
-        }
-
-        byte[] packet = AdbProtocol.generateClose(localId, remoteId);
-        adbConn.outputStream.write(packet);
-        adbConn.outputStream.flush();
-    }
-
-    /**
-     * Retreives whether the stream is closed or not
-     *
-     * @return True if the stream is close, false if not
-     */
-    public boolean isClosed() {
-        return isClosed;
-    }
-}

+ 0 - 27
app/src/main/java/org/las2mile/scrcpy/adblib/LICENSE

@@ -1,27 +0,0 @@
-Copyright (c) 2013, Cameron Gutman
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-  Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-  Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimer in the documentation and/or
-  other materials provided with the distribution.
-
-  Neither the name of the {organization} nor the names of its
-  contributors may be used to endorse or promote products derived from
-  this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.