blob: 36f8eadc2d0fe96e9d8a543d8bf6f73c8a686d68 [file] [log] [blame]
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +00001//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Other libraries and framework includes
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000011#include "llvm/ADT/SmallVector.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/STLExtras.h"
14
15// Project includes
16#include "AdbClient.h"
17
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000018#include <algorithm>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000019#include <sstream>
20
21using namespace lldb;
22using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000023using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000024
25namespace {
26
27const uint32_t kConnTimeout = 10000; // 10 ms
28const char * kOKAY = "OKAY";
29const char * kFAIL = "FAIL";
30
31} // namespace
32
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000033Error
34AdbClient::CreateByDeviceID (const char* device_id, AdbClient &adb)
35{
36 DeviceIDList connect_devices;
37 auto error = adb.GetDevices (connect_devices);
38 if (error.Fail ())
39 return error;
40
41 if (device_id)
42 {
43 auto find_it = std::find(connect_devices.begin (), connect_devices.end (), device_id);
44 if (find_it == connect_devices.end ())
45 return Error ("Device \"%s\" not found", device_id);
46
47 adb.SetDeviceID (*find_it);
48 }
49 else
50 {
51 if (connect_devices.size () != 1)
Oleksiy Vyalove17800c2015-04-10 03:59:52 +000052 return Error ("Expected a single connected device, got instead %" PRIu64, static_cast<uint64_t>(connect_devices.size ()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000053
54 adb.SetDeviceID (connect_devices.front ());
55 }
56 return error;
57}
58
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000059AdbClient::AdbClient (const std::string &device_id)
60 : m_device_id (device_id)
61{
62}
63
64void
65AdbClient::SetDeviceID (const std::string& device_id)
66{
67 m_device_id = device_id;
68}
69
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000070const std::string&
71AdbClient::GetDeviceID() const
72{
73 return m_device_id;
74}
75
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000076Error
77AdbClient::Connect ()
78{
79 Error error;
80 m_conn.Connect ("connect://localhost:5037", &error);
81
82 return error;
83}
84
85Error
86AdbClient::GetDevices (DeviceIDList &device_list)
87{
88 device_list.clear ();
89
90 auto error = SendMessage ("host:devices");
91 if (error.Fail ())
92 return error;
93
94 error = ReadResponseStatus ();
95 if (error.Fail ())
96 return error;
97
98 std::string in_buffer;
99 error = ReadMessage (in_buffer);
100
101 llvm::StringRef response (in_buffer);
102 llvm::SmallVector<llvm::StringRef, 4> devices;
103 response.split (devices, "\n", -1, false);
104
105 for (const auto device: devices)
106 device_list.push_back (device.split ('\t').first);
107
108 return error;
109}
110
111Error
112AdbClient::SetPortForwarding (const uint16_t port)
113{
114 char message[48];
115 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
116
117 const auto error = SendDeviceMessage (message);
118 if (error.Fail ())
119 return error;
120
121 return ReadResponseStatus ();
122}
123
124Error
125AdbClient::DeletePortForwarding (const uint16_t port)
126{
127 char message[32];
128 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
129
130 const auto error = SendDeviceMessage (message);
131 if (error.Fail ())
132 return error;
133
134 return ReadResponseStatus ();
135}
136
137Error
138AdbClient::SendMessage (const std::string &packet)
139{
140 auto error = Connect ();
141 if (error.Fail ())
142 return error;
143
144 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000145 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000146
147 ConnectionStatus status;
148
149 m_conn.Write (length_buffer, 4, status, &error);
150 if (error.Fail ())
151 return error;
152
153 m_conn.Write (packet.c_str (), packet.size (), status, &error);
154 return error;
155}
156
157Error
158AdbClient::SendDeviceMessage (const std::string &packet)
159{
160 std::ostringstream msg;
161 msg << "host-serial:" << m_device_id << ":" << packet;
162 return SendMessage (msg.str ());
163}
164
165Error
166AdbClient::ReadMessage (std::string &message)
167{
168 message.clear ();
169
170 char buffer[5];
171 buffer[4] = 0;
172
173 Error error;
174 ConnectionStatus status;
175
176 m_conn.Read (buffer, 4, kConnTimeout, status, &error);
177 if (error.Fail ())
178 return error;
179
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000180 int packet_len = 0;
181 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000182 std::string result (packet_len, 0);
183 m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error);
184 if (error.Success ())
185 result.swap (message);
186
187 return error;
188}
189
190Error
191AdbClient::ReadResponseStatus()
192{
193 char buffer[5];
194
195 static const size_t packet_len = 4;
196 buffer[packet_len] = 0;
197
198 Error error;
199 ConnectionStatus status;
200
201 m_conn.Read (buffer, packet_len, kConnTimeout, status, &error);
202 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000203 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000204
205 if (strncmp (buffer, kOKAY, packet_len) != 0)
206 {
207 if (strncmp (buffer, kFAIL, packet_len) == 0)
208 {
209 std::string error_message;
210 error = ReadMessage (error_message);
211 if (error.Fail ())
212 return error;
213 error.SetErrorString (error_message.c_str ());
214 }
215 else
216 error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer);
217 }
218
219 return error;
220}