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
close()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
connect()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
sendRequest(const char * fmt,...) const79 bool AdbConnection::sendRequest(const char* fmt, ...) const {
80 if (m_fd == -1) {
81 ALOGE("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 ALOGV("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
printFailureMessage(int fd)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 ALOG_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 ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
134 return;
135 }
136 msg[res] = 0;
137
138 // Tell somebody about it
139 ALOGE("Received failure from adb: %s", msg);
140
141 // Cleanup
142 delete[] msg;
143 }
144
145 #define ADB_RESPONSE_LENGTH 4
146
checkOkayResponse() const147 bool AdbConnection::checkOkayResponse() const {
148 ALOG_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 ALOGV("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 ALOGE("Incorrect response from adb - '%.*s'", res, buf);
167 return false;
168 }
169
clearDevices()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
getDeviceList()176 const DeviceList& AdbConnection::getDeviceList() {
177 // Clear the current device list
178 clearDevices();
179
180 if (m_fd == -1) {
181 ALOGE("Connection is closed");
182 return m_devices;
183 }
184
185 // Try to send the device list request
186 if (!sendRequest("host:devices")) {
187 ALOGE("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 ALOGE("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 ALOGV("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