Home | History | Annotate | Download | only in client
      1 /*
      2  * Copyright 2009, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #define LOG_TAG "wdsclient"
     27 
     28 #include "AdbConnection.h"
     29 #include "ClientUtils.h"
     30 #include "Device.h"
     31 #include <arpa/inet.h>
     32 #include <errno.h>
     33 #include <string.h>
     34 #include <sys/socket.h>
     35 #include <sys/types.h>
     36 #include <utils/Log.h>
     37 
     38 void AdbConnection::close() {
     39     if (m_fd != -1) {
     40         shutdown(m_fd, SHUT_RDWR);
     41         ::close(m_fd);
     42         m_fd = -1;
     43     }
     44 }
     45 
     46 // Default adb port
     47 #define ADB_PORT 5037
     48 
     49 bool AdbConnection::connect() {
     50     // Some commands (host:devices for example) close the connection so we call
     51     // connect after the response.
     52     close();
     53 
     54     m_fd = socket(PF_INET, SOCK_STREAM, 0);
     55     if (m_fd < 0) {
     56         log_errno("Failed to create socket for connecting to adb");
     57         return false;
     58     }
     59 
     60     // Create the socket address struct
     61     sockaddr_in adb;
     62     createTcpSocket(adb, ADB_PORT);
     63 
     64     // Connect to adb
     65     if (::connect(m_fd, (sockaddr*) &adb, sizeof(adb)) < 0) {
     66         log_errno("Failed to connect to adb");
     67         return false;
     68     }
     69 
     70     // Connected
     71     return true;
     72 }
     73 
     74 // Adb protocol stuff
     75 #define MAX_COMMAND_LENGTH 1024
     76 #define PAYLOAD_LENGTH 4
     77 #define PAYLOAD_FORMAT "%04X"
     78 
     79 bool AdbConnection::sendRequest(const char* fmt, ...) const {
     80     if (m_fd == -1) {
     81         LOGE("Connection is closed");
     82         return false;
     83     }
     84 
     85     // Build the command (service)
     86     char buf[MAX_COMMAND_LENGTH];
     87     va_list args;
     88     va_start(args, fmt);
     89     int res = vsnprintf(buf, MAX_COMMAND_LENGTH, fmt, args);
     90     va_end(args);
     91 
     92     LOGV("Sending command: %04X%.*s", res, res, buf);
     93 
     94     // Construct the payload length
     95     char payloadLen[PAYLOAD_LENGTH + 1];
     96     snprintf(payloadLen, sizeof(payloadLen), PAYLOAD_FORMAT, res);
     97 
     98     // First, send the payload length
     99     if (send(m_fd, payloadLen, PAYLOAD_LENGTH, 0) < 0) {
    100         log_errno("Failure when sending payload");
    101         return false;
    102     }
    103 
    104     // Send the actual command
    105     if (send(m_fd, buf, res, 0) < 0) {
    106         log_errno("Failure when sending command");
    107         return false;
    108     }
    109 
    110     // Check for the OKAY from adb
    111     return checkOkayResponse();
    112 }
    113 
    114 static void printFailureMessage(int fd) {
    115     // Grab the payload length
    116     char lenStr[PAYLOAD_LENGTH + 1];
    117     int payloadLen = recv(fd, lenStr, sizeof(lenStr) - 1, 0);
    118     LOG_ASSERT(payloadLen == PAYLOAD_LENGTH, "Incorrect payload size");
    119     lenStr[PAYLOAD_LENGTH] = 0;
    120 
    121     // Parse the hex payload
    122     payloadLen = strtol(lenStr, NULL, 16);
    123     if (payloadLen < 0)
    124         return;
    125 
    126     // Grab the message
    127     char* msg = new char[payloadLen + 1]; // include null-terminator
    128     int res = recv(fd, msg, payloadLen, 0);
    129     if (res < 0) {
    130         log_errno("Failure reading failure message from adb");
    131         return;
    132     } else if (res != payloadLen) {
    133         LOGE("Incorrect payload length %d - expected %d", res, payloadLen);
    134         return;
    135     }
    136     msg[res] = 0;
    137 
    138     // Tell somebody about it
    139     LOGE("Received failure from adb: %s", msg);
    140 
    141     // Cleanup
    142     delete[] msg;
    143 }
    144 
    145 #define ADB_RESPONSE_LENGTH 4
    146 
    147 bool AdbConnection::checkOkayResponse() const {
    148     LOG_ASSERT(m_fd != -1, "Connection has been closed!");
    149 
    150     char buf[ADB_RESPONSE_LENGTH];
    151     int res = recv(m_fd, buf, sizeof(buf), 0);
    152     if (res < 0) {
    153         log_errno("Failure reading response from adb");
    154         return false;
    155     }
    156 
    157     // Check for a response other than OKAY/FAIL
    158     if ((res == ADB_RESPONSE_LENGTH) && (strncmp(buf, "OKAY", res) == 0)) {
    159         LOGV("Command OKAY");
    160         return true;
    161     } else if (strncmp(buf, "FAIL", ADB_RESPONSE_LENGTH) == 0) {
    162         // Something happened, print out the reason for failure
    163         printFailureMessage(m_fd);
    164         return false;
    165     }
    166     LOGE("Incorrect response from adb - '%.*s'", res, buf);
    167     return false;
    168 }
    169 
    170 void AdbConnection::clearDevices() {
    171     for (unsigned i = 0; i < m_devices.size(); i++)
    172         delete m_devices.editItemAt(i);
    173     m_devices.clear();
    174 }
    175 
    176 const DeviceList& AdbConnection::getDeviceList() {
    177     // Clear the current device list
    178     clearDevices();
    179 
    180     if (m_fd == -1) {
    181         LOGE("Connection is closed");
    182         return m_devices;
    183     }
    184 
    185     // Try to send the device list request
    186     if (!sendRequest("host:devices")) {
    187         LOGE("Failed to get device list from adb");
    188         return m_devices;
    189     }
    190 
    191     // Get the payload length
    192     char lenStr[PAYLOAD_LENGTH + 1];
    193     int res = recv(m_fd, lenStr, sizeof(lenStr) - 1, 0);
    194     if (res < 0) {
    195         log_errno("Failure to read payload size of device list");
    196         return m_devices;
    197     }
    198     lenStr[PAYLOAD_LENGTH] = 0;
    199 
    200     // Parse the hex payload
    201     int payloadLen = strtol(lenStr, NULL, 16);
    202     if (payloadLen < 0)
    203         return m_devices;
    204 
    205     // Grab the list of devices. The format is as follows:
    206     // <serialno><tab><state><newline>
    207     char* msg = new char[payloadLen + 1];
    208     res = recv(m_fd, msg, payloadLen, 0);
    209     if (res < 0) {
    210         log_errno("Failure reading the device list");
    211         return m_devices;
    212     } else if (res != payloadLen) {
    213         LOGE("Incorrect payload length %d - expected %d", res, payloadLen);
    214         return m_devices;
    215     }
    216     msg[res] = 0;
    217 
    218     char serial[32];
    219     char state[32];
    220     int numRead;
    221     char* ptr = msg;
    222     while (sscanf(ptr, "%31s\t%31s\n%n", serial, state, &numRead) > 1) {
    223         Device::DeviceType t = Device::DEVICE;
    224         static const char emulator[] = "emulator-";
    225         if (strncmp(serial, emulator, sizeof(emulator) - 1) == 0)
    226             t = Device::EMULATOR;
    227         LOGV("Adding device %s (%s)", serial, state);
    228         m_devices.add(new Device(serial, t, this));
    229 
    230         // Reset for the next line
    231         ptr += numRead;
    232     }
    233     // Cleanup
    234     delete[] msg;
    235 
    236     return m_devices;
    237 }
    238