11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/Support/FileUtilities.h"
43using namespace std::chrono;
46static const char *
kOKAY =
"OKAY";
47static const char *
kFAIL =
"FAIL";
48static const char *
kDATA =
"DATA";
49static const char *
kDONE =
"DONE";
51static const char *
kSEND =
"SEND";
52static const char *
kRECV =
"RECV";
53static const char *
kSTAT =
"STAT";
68 char *read_buffer =
static_cast<char *
>(buffer);
70 auto now = steady_clock::now();
72 size_t total_read_bytes = 0;
73 while (total_read_bytes < size && now < deadline) {
75 conn.
Read(read_buffer + total_read_bytes, size - total_read_bytes,
76 duration_cast<microseconds>(deadline - now), status, &
error);
79 total_read_bytes += read_bytes;
82 now = steady_clock::now();
84 if (total_read_bytes < size)
86 "Unable to read requested number of bytes. Connection status: %d.",
94 std::string android_serial;
95 if (!device_id.empty())
96 android_serial = device_id;
97 else if (
const char *env_serial = std::getenv(
"ANDROID_SERIAL"))
98 android_serial = env_serial;
100 if (android_serial.empty()) {
106 if (connected_devices.size() != 1)
108 "Expected a single connected device, got instead %zu - try "
109 "setting 'ANDROID_SERIAL'",
110 connected_devices.size());
132 m_conn = std::make_unique<ConnectionFileDescriptor>();
133 std::string port =
"5037";
134 if (
const char *env_port = std::getenv(
"ANDROID_ADB_SERVER_PORT")) {
137 std::string uri =
"connect://127.0.0.1:" + port;
154 std::vector<char> in_buffer;
157 llvm::StringRef response(&in_buffer[0], in_buffer.size());
158 llvm::SmallVector<llvm::StringRef, 4> devices;
159 response.split(devices,
"\n", -1,
false);
161 for (
const auto &device : devices)
162 device_list.push_back(std::string(device.split(
'\t').first));
171 const uint16_t remote_port) {
173 snprintf(message,
sizeof(message),
"forward:tcp:%d;tcp:%d", local_port,
185 llvm::StringRef remote_socket_name,
188 const char *sock_namespace_str =
192 snprintf(message,
sizeof(message),
"forward:tcp:%d;%s:%s", local_port,
193 sock_namespace_str, remote_socket_name.str().c_str());
204 snprintf(message,
sizeof(message),
"killforward:tcp:%d", local_port);
215 if (!
m_conn || reconnect) {
221 char length_buffer[5];
222 snprintf(length_buffer,
sizeof(length_buffer),
"%04x",
223 static_cast<int>(packet.size()));
231 m_conn->Write(packet.c_str(), packet.size(), status, &
error);
236 std::ostringstream msg;
237 msg <<
"host-serial:" <<
m_device_id <<
":" << packet;
251 unsigned int packet_len = 0;
252 sscanf(buffer,
"%x", &packet_len);
254 message.resize(packet_len, 0);
263 milliseconds timeout) {
264 auto start = steady_clock::now();
271 auto end = steady_clock::now();
276 size_t n =
m_conn->Read(buffer,
sizeof(buffer),
277 duration_cast<microseconds>(timeout -
elapsed),
280 message.insert(message.end(), &buffer[0], &buffer[n]);
288 static const size_t packet_len = 4;
289 response_id[packet_len] = 0;
295 if (strncmp(response_id,
kOKAY, packet_len) != 0)
302 if (strcmp(response_id,
kFAIL) != 0)
304 "Got unexpected response id from adb: \"%s\"", response_id);
306 std::vector<char> error_message;
308 if (!
error.Success())
310 return Status(std::string(&error_message[0], error_message.size()));
314 std::ostringstream msg;
328 "Failed to switch to device transport: %s",
error.AsCString());
347 return ::ReadAllBytes(*
m_conn, buffer, size);
351 std::vector<char> &output_buf) {
357 "Failed to switch to device transport: %s",
error.AsCString());
360 adb_command.
Printf(
"shell:%s", command);
375 static const char *kShellPrefix =
"/system/bin/sh:";
376 if (output_buf.size() > strlen(kShellPrefix)) {
377 if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix)))
379 "Shell command %s failed: %s", command,
380 std::string(output_buf.begin(), output_buf.end()).c_str());
387 std::string *output) {
388 std::vector<char> output_buffer;
394 output->assign(output_buffer.begin(), output_buffer.end());
400 std::vector<char> output_buffer;
405 const auto output_filename = output_file_spec.
GetPath();
407 llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::OF_None);
410 output_filename.c_str());
412 dst.write(&output_buffer[0], output_buffer.size());
416 output_filename.c_str());
420std::unique_ptr<AdbClient::SyncService>
422 std::unique_ptr<SyncService> sync_service;
432 const auto local_file_path = local_file.
GetPath();
433 llvm::FileRemover local_file_remover(local_file_path);
436 llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::OF_None);
439 local_file_path.c_str());
441 const auto remote_file_path = remote_file.
GetPath(
false);
443 remote_file_path.c_str());
447 std::vector<char> chunk;
454 dst.write(&chunk[0], chunk.size());
459 local_file_path.c_str());
461 local_file_remover.releaseFile();
467 const auto local_file_path(local_file.
GetPath());
468 std::ifstream src(local_file_path.c_str(), std::ios::in | std::ios::binary);
471 local_file_path.c_str());
473 std::stringstream file_description;
475 std::string file_description_str = file_description.str();
476 auto error = SendSyncRequest(
kSEND, file_description_str.length(),
477 file_description_str.c_str());
482 while (!src.eof() && !src.read(chunk,
kMaxPushData).bad()) {
483 size_t chunk_size = src.gcount();
484 error = SendSyncRequest(
kDATA, chunk_size, chunk);
489 error = SendSyncRequest(
495 std::string response_id;
497 error = ReadSyncHeader(response_id, data_len);
501 if (response_id ==
kFAIL) {
502 std::string error_message(data_len, 0);
506 "Failed to read DONE error message: %s",
error.AsCString());
508 error_message.c_str());
509 }
else if (response_id !=
kOKAY)
511 response_id.c_str());
517 local_file_path.c_str());
522 uint32_t &mode, uint32_t &size,
524 const std::string remote_file_path(remote_file.
GetPath(
false));
525 auto error = SendSyncRequest(
kSTAT, remote_file_path.length(),
526 remote_file_path.c_str());
531 static const size_t stat_len = strlen(
kSTAT);
532 static const size_t response_len = stat_len + (
sizeof(uint32_t) * 3);
534 std::vector<char> buffer(response_len);
544 const void *command = extractor.
GetData(&offset, stat_len);
547 const char *command_str =
static_cast<const char *
>(command);
548 if (strncmp(command_str,
kSTAT, stat_len))
552 mode = extractor.
GetU32(&offset);
553 size = extractor.
GetU32(&offset);
554 mtime = extractor.
GetU32(&offset);
560 return executeCommand([
this, &remote_file, &local_file]() {
561 return internalPullFile(remote_file, local_file);
567 return executeCommand([
this, &local_file, &remote_file]() {
568 return internalPushFile(local_file, remote_file);
573 uint32_t &size, uint32_t &mtime) {
574 return executeCommand([
this, &remote_file, &mode, &size, &mtime]() {
575 return internalStat(remote_file, mode, size, mtime);
584 :
m_conn(std::move(conn)) {}
601 const uint32_t data_len,
604 encoder.
AppendData(llvm::StringRef(request_id));
606 llvm::ArrayRef<uint8_t> bytes = encoder.
GetData();
619 uint32_t &data_len) {
623 if (
error.Success()) {
624 response_id.assign(&buffer[0], 4);
627 data_len = extractor.
GetU32(&offset);
637 std::string response_id;
639 auto error = ReadSyncHeader(response_id, data_len);
643 if (response_id ==
kDATA) {
644 buffer.resize(data_len, 0);
648 }
else if (response_id ==
kDONE) {
650 }
else if (response_id ==
kFAIL) {
651 std::string error_message(data_len, 0);
655 "Failed to read pull error message: %s",
error.AsCString());
657 error_message.c_str());
660 "Pull failed with unknown response: %s", response_id.c_str());
666 return ::ReadAllBytes(*
m_conn, buffer, size);
static Status ReadAllBytes(Connection &conn, void *buffer, size_t size)
static const char * kSTAT
static const size_t kSyncPacketLen
static const char * kSocketNamespaceAbstract
static const seconds kReadTimeout(20)
static const char * kSocketNamespaceFileSystem
static const char * kDATA
static const char * kRECV
static const char * kSEND
static const char * kOKAY
static const char * kFAIL
static const uint32_t kDefaultMode
static const size_t kMaxPushData
static const char * kDONE
static llvm::raw_ostream & error(Stream &strm)
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
A communication connection class.
virtual size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr)=0
The read function that attempts to read from the connection.
An binary data encoding class.
llvm::ArrayRef< uint8_t > GetData() const
Get a access to the bytes that this references.
void AppendU32(uint32_t value)
void AppendData(llvm::StringRef data)
Append a bytes to the end of the owned data.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
static FileSystem & Instance()
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
A class that represents a running process on the host machine.
ConnectionStatus
Connection Status Types.
@ eConnectionStatusSuccess
Success.