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