1 //===-- 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 11 #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 18 #include <algorithm> 19 #include <sstream> 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::platform_android; 24 25 namespace { 26 27 const uint32_t kConnTimeout = 10000; // 10 ms 28 const char * kOKAY = "OKAY"; 29 const char * kFAIL = "FAIL"; 30 31 } // namespace 32 33 Error 34 AdbClient::CreateByDeviceID(const std::string &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.empty()) 42 { 43 if (connect_devices.size() != 1) 44 return Error("Expected a single connected device, got instead %" PRIu64, 45 static_cast<uint64_t>(connect_devices.size())); 46 47 adb.SetDeviceID(connect_devices.front()); 48 } 49 else 50 { 51 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id); 52 if (find_it == connect_devices.end()) 53 return Error("Device \"%s\" not found", device_id.c_str()); 54 55 adb.SetDeviceID(*find_it); 56 } 57 return error; 58 } 59 60 AdbClient::AdbClient (const std::string &device_id) 61 : m_device_id (device_id) 62 { 63 } 64 65 void 66 AdbClient::SetDeviceID (const std::string& device_id) 67 { 68 m_device_id = device_id; 69 } 70 71 const std::string& 72 AdbClient::GetDeviceID() const 73 { 74 return m_device_id; 75 } 76 77 Error 78 AdbClient::Connect () 79 { 80 Error error; 81 m_conn.Connect ("connect://localhost:5037", &error); 82 83 return error; 84 } 85 86 Error 87 AdbClient::GetDevices (DeviceIDList &device_list) 88 { 89 device_list.clear (); 90 91 auto error = SendMessage ("host:devices"); 92 if (error.Fail ()) 93 return error; 94 95 error = ReadResponseStatus (); 96 if (error.Fail ()) 97 return error; 98 99 std::string in_buffer; 100 error = ReadMessage (in_buffer); 101 102 llvm::StringRef response (in_buffer); 103 llvm::SmallVector<llvm::StringRef, 4> devices; 104 response.split (devices, "\n", -1, false); 105 106 for (const auto device: devices) 107 device_list.push_back (device.split ('\t').first); 108 109 return error; 110 } 111 112 Error 113 AdbClient::SetPortForwarding (const uint16_t port) 114 { 115 char message[48]; 116 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port); 117 118 const auto error = SendDeviceMessage (message); 119 if (error.Fail ()) 120 return error; 121 122 return ReadResponseStatus (); 123 } 124 125 Error 126 AdbClient::DeletePortForwarding (const uint16_t port) 127 { 128 char message[32]; 129 snprintf (message, sizeof (message), "killforward:tcp:%d", port); 130 131 const auto error = SendDeviceMessage (message); 132 if (error.Fail ()) 133 return error; 134 135 return ReadResponseStatus (); 136 } 137 138 Error 139 AdbClient::SendMessage (const std::string &packet) 140 { 141 auto error = Connect (); 142 if (error.Fail ()) 143 return error; 144 145 char length_buffer[5]; 146 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ())); 147 148 ConnectionStatus status; 149 150 m_conn.Write (length_buffer, 4, status, &error); 151 if (error.Fail ()) 152 return error; 153 154 m_conn.Write (packet.c_str (), packet.size (), status, &error); 155 return error; 156 } 157 158 Error 159 AdbClient::SendDeviceMessage (const std::string &packet) 160 { 161 std::ostringstream msg; 162 msg << "host-serial:" << m_device_id << ":" << packet; 163 return SendMessage (msg.str ()); 164 } 165 166 Error 167 AdbClient::ReadMessage (std::string &message) 168 { 169 message.clear (); 170 171 char buffer[5]; 172 buffer[4] = 0; 173 174 Error error; 175 ConnectionStatus status; 176 177 m_conn.Read (buffer, 4, kConnTimeout, status, &error); 178 if (error.Fail ()) 179 return error; 180 181 int packet_len = 0; 182 sscanf (buffer, "%x", &packet_len); 183 std::string result (packet_len, 0); 184 m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error); 185 if (error.Success ()) 186 result.swap (message); 187 188 return error; 189 } 190 191 Error 192 AdbClient::ReadResponseStatus() 193 { 194 char buffer[5]; 195 196 static const size_t packet_len = 4; 197 buffer[packet_len] = 0; 198 199 Error error; 200 ConnectionStatus status; 201 202 m_conn.Read (buffer, packet_len, kConnTimeout, status, &error); 203 if (error.Fail ()) 204 return error; 205 206 if (strncmp (buffer, kOKAY, packet_len) != 0) 207 { 208 if (strncmp (buffer, kFAIL, packet_len) == 0) 209 { 210 std::string error_message; 211 error = ReadMessage (error_message); 212 if (error.Fail ()) 213 return error; 214 error.SetErrorString (error_message.c_str ()); 215 } 216 else 217 error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer); 218 } 219 220 return error; 221 } 222