18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright 2009, The Android Open Source Project
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
163298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define LOG_TAG "wdsclient"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AdbConnection.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ClientUtils.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Device.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <arpa/inet.h>
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <errno.h>
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <string.h>
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <sys/socket.h>
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <sys/types.h>
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <utils/Log.h>
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AdbConnection::close() {
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_fd != -1) {
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shutdown(m_fd, SHUT_RDWR);
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ::close(m_fd);
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_fd = -1;
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Default adb port
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define ADB_PORT 5037
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AdbConnection::connect() {
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Some commands (host:devices for example) close the connection so we call
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // connect after the response.
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    close();
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_fd = socket(PF_INET, SOCK_STREAM, 0);
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_fd < 0) {
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failed to create socket for connecting to adb");
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Create the socket address struct
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    sockaddr_in adb;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    createTcpSocket(adb, ADB_PORT);
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Connect to adb
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (::connect(m_fd, (sockaddr*) &adb, sizeof(adb)) < 0) {
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failed to connect to adb");
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Connected
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Adb protocol stuff
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define MAX_COMMAND_LENGTH 1024
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define PAYLOAD_LENGTH 4
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define PAYLOAD_FORMAT "%04X"
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AdbConnection::sendRequest(const char* fmt, ...) const {
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_fd == -1) {
81f6b86ce97ca983128ec58f77cb4932774845f072Steve Block        ALOGE("Connection is closed");
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Build the command (service)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char buf[MAX_COMMAND_LENGTH];
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    va_list args;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    va_start(args, fmt);
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int res = vsnprintf(buf, MAX_COMMAND_LENGTH, fmt, args);
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    va_end(args);
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
922df3aefb377b3f3c4af3b548b1980d8c8ae56844Steve Block    ALOGV("Sending command: %04X%.*s", res, res, buf);
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Construct the payload length
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char payloadLen[PAYLOAD_LENGTH + 1];
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    snprintf(payloadLen, sizeof(payloadLen), PAYLOAD_FORMAT, res);
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // First, send the payload length
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (send(m_fd, payloadLen, PAYLOAD_LENGTH, 0) < 0) {
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure when sending payload");
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Send the actual command
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (send(m_fd, buf, res, 0) < 0) {
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure when sending command");
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check for the OKAY from adb
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return checkOkayResponse();
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void printFailureMessage(int fd) {
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Grab the payload length
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char lenStr[PAYLOAD_LENGTH + 1];
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int payloadLen = recv(fd, lenStr, sizeof(lenStr) - 1, 0);
1186dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(payloadLen == PAYLOAD_LENGTH, "Incorrect payload size");
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lenStr[PAYLOAD_LENGTH] = 0;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Parse the hex payload
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    payloadLen = strtol(lenStr, NULL, 16);
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (payloadLen < 0)
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Grab the message
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* msg = new char[payloadLen + 1]; // include null-terminator
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int res = recv(fd, msg, payloadLen, 0);
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (res < 0) {
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure reading failure message from adb");
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (res != payloadLen) {
133f6b86ce97ca983128ec58f77cb4932774845f072Steve Block        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    msg[res] = 0;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Tell somebody about it
139f6b86ce97ca983128ec58f77cb4932774845f072Steve Block    ALOGE("Received failure from adb: %s", msg);
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Cleanup
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] msg;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define ADB_RESPONSE_LENGTH 4
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AdbConnection::checkOkayResponse() const {
1486dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(m_fd != -1, "Connection has been closed!");
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char buf[ADB_RESPONSE_LENGTH];
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int res = recv(m_fd, buf, sizeof(buf), 0);
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (res < 0) {
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure reading response from adb");
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check for a response other than OKAY/FAIL
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ((res == ADB_RESPONSE_LENGTH) && (strncmp(buf, "OKAY", res) == 0)) {
1592df3aefb377b3f3c4af3b548b1980d8c8ae56844Steve Block        ALOGV("Command OKAY");
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (strncmp(buf, "FAIL", ADB_RESPONSE_LENGTH) == 0) {
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Something happened, print out the reason for failure
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        printFailureMessage(m_fd);
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
166f6b86ce97ca983128ec58f77cb4932774845f072Steve Block    ALOGE("Incorrect response from adb - '%.*s'", res, buf);
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AdbConnection::clearDevices() {
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i < m_devices.size(); i++)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete m_devices.editItemAt(i);
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_devices.clear();
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst DeviceList& AdbConnection::getDeviceList() {
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Clear the current device list
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    clearDevices();
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_fd == -1) {
181f6b86ce97ca983128ec58f77cb4932774845f072Steve Block        ALOGE("Connection is closed");
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Try to send the device list request
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!sendRequest("host:devices")) {
187f6b86ce97ca983128ec58f77cb4932774845f072Steve Block        ALOGE("Failed to get device list from adb");
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the payload length
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char lenStr[PAYLOAD_LENGTH + 1];
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int res = recv(m_fd, lenStr, sizeof(lenStr) - 1, 0);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (res < 0) {
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure to read payload size of device list");
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lenStr[PAYLOAD_LENGTH] = 0;
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Parse the hex payload
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int payloadLen = strtol(lenStr, NULL, 16);
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (payloadLen < 0)
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Grab the list of devices. The format is as follows:
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // <serialno><tab><state><newline>
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* msg = new char[payloadLen + 1];
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    res = recv(m_fd, msg, payloadLen, 0);
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (res < 0) {
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        log_errno("Failure reading the device list");
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (res != payloadLen) {
213f6b86ce97ca983128ec58f77cb4932774845f072Steve Block        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_devices;
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    msg[res] = 0;
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char serial[32];
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char state[32];
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int numRead;
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* ptr = msg;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (sscanf(ptr, "%31s\t%31s\n%n", serial, state, &numRead) > 1) {
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Device::DeviceType t = Device::DEVICE;
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        static const char emulator[] = "emulator-";
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (strncmp(serial, emulator, sizeof(emulator) - 1) == 0)
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            t = Device::EMULATOR;
2272df3aefb377b3f3c4af3b548b1980d8c8ae56844Steve Block        ALOGV("Adding device %s (%s)", serial, state);
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_devices.add(new Device(serial, t, this));
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Reset for the next line
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ptr += numRead;
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Cleanup
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] msg;
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_devices;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
238