• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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