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)
107 return Status(
"Expected a single connected device, got instead %zu - try "
108 "setting 'ANDROID_SERIAL'",
109 connected_devices.size());
131 m_conn = std::make_unique<ConnectionFileDescriptor>();
132 std::string port =
"5037";
133 if (
const char *env_port = std::getenv(
"ANDROID_ADB_SERVER_PORT")) {
136 std::string uri =
"connect://127.0.0.1:" + port;
153 std::vector<char> in_buffer;
156 llvm::StringRef response(&in_buffer[0], in_buffer.size());
157 llvm::SmallVector<llvm::StringRef, 4> devices;
158 response.split(devices,
"\n", -1,
false);
160 for (
const auto &device : devices)
161 device_list.push_back(std::string(device.split(
'\t').first));
170 const uint16_t remote_port) {
172 snprintf(message,
sizeof(message),
"forward:tcp:%d;tcp:%d", local_port,
184 llvm::StringRef remote_socket_name,
187 const char *sock_namespace_str =
191 snprintf(message,
sizeof(message),
"forward:tcp:%d;%s:%s", local_port,
192 sock_namespace_str, remote_socket_name.str().c_str());
203 snprintf(message,
sizeof(message),
"killforward:tcp:%d", local_port);
214 if (!
m_conn || reconnect) {
220 char length_buffer[5];
221 snprintf(length_buffer,
sizeof(length_buffer),
"%04x",
222 static_cast<int>(packet.size()));
230 m_conn->Write(packet.c_str(), packet.size(), status, &
error);
235 std::ostringstream msg;
236 msg <<
"host-serial:" <<
m_device_id <<
":" << packet;
250 unsigned int packet_len = 0;
251 sscanf(buffer,
"%x", &packet_len);
253 message.resize(packet_len, 0);
262 milliseconds timeout) {
263 auto start = steady_clock::now();
270 auto end = steady_clock::now();
273 return Status(
"Timed out");
275 size_t n =
m_conn->Read(buffer,
sizeof(buffer),
276 duration_cast<microseconds>(timeout -
elapsed),
279 message.insert(message.end(), &buffer[0], &buffer[n]);
287 static const size_t packet_len = 4;
288 response_id[packet_len] = 0;
294 if (strncmp(response_id,
kOKAY, packet_len) != 0)
301 if (strcmp(response_id,
kFAIL) != 0)
302 return Status(
"Got unexpected response id from adb: \"%s\"", response_id);
304 std::vector<char> error_message;
307 error.SetErrorString(
308 std::string(&error_message[0], error_message.size()).c_str());
314 std::ostringstream msg;
327 return Status(
"Failed to switch to device transport: %s",
332 return Status(
"Sync failed: %s",
error.AsCString());
346 return ::ReadAllBytes(*
m_conn, buffer, size);
350 std::vector<char> &output_buf) {
355 return Status(
"Failed to switch to device transport: %s",
359 adb_command.
Printf(
"shell:%s", command);
374 static const char *kShellPrefix =
"/system/bin/sh:";
375 if (output_buf.size() > strlen(kShellPrefix)) {
376 if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix)))
377 return Status(
"Shell command %s failed: %s", command,
378 std::string(output_buf.begin(), output_buf.end()).c_str());
385 std::string *output) {
386 std::vector<char> output_buffer;
392 output->assign(output_buffer.begin(), output_buffer.end());
398 std::vector<char> output_buffer;
403 const auto output_filename = output_file_spec.
GetPath();
405 llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::OF_None);
407 return Status(
"Unable to open local file %s", output_filename.c_str());
409 dst.write(&output_buffer[0], output_buffer.size());
412 return Status(
"Failed to write file %s", output_filename.c_str());
416std::unique_ptr<AdbClient::SyncService>
418 std::unique_ptr<SyncService> sync_service;
428 const auto local_file_path = local_file.
GetPath();
429 llvm::FileRemover local_file_remover(local_file_path);
432 llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::OF_None);
434 return Status(
"Unable to open local file %s", local_file_path.c_str());
436 const auto remote_file_path = remote_file.
GetPath(
false);
438 remote_file_path.c_str());
442 std::vector<char> chunk;
449 dst.write(&chunk[0], chunk.size());
453 return Status(
"Failed to write file %s", local_file_path.c_str());
455 local_file_remover.releaseFile();
461 const auto local_file_path(local_file.
GetPath());
462 std::ifstream src(local_file_path.c_str(), std::ios::in | std::ios::binary);
464 return Status(
"Unable to open local file %s", local_file_path.c_str());
466 std::stringstream file_description;
468 std::string file_description_str = file_description.str();
469 auto error = SendSyncRequest(
kSEND, file_description_str.length(),
470 file_description_str.c_str());
475 while (!src.eof() && !src.read(chunk,
kMaxPushData).bad()) {
476 size_t chunk_size = src.gcount();
477 error = SendSyncRequest(
kDATA, chunk_size, chunk);
479 return Status(
"Failed to send file chunk: %s",
error.AsCString());
481 error = SendSyncRequest(
487 std::string response_id;
489 error = ReadSyncHeader(response_id, data_len);
491 return Status(
"Failed to read DONE response: %s",
error.AsCString());
492 if (response_id ==
kFAIL) {
493 std::string error_message(data_len, 0);
496 return Status(
"Failed to read DONE error message: %s",
error.AsCString());
497 return Status(
"Failed to push file: %s", error_message.c_str());
498 }
else if (response_id !=
kOKAY)
499 return Status(
"Got unexpected DONE response: %s", response_id.c_str());
504 return Status(
"Failed read on %s", local_file_path.c_str());
509 uint32_t &mode, uint32_t &size,
511 const std::string remote_file_path(remote_file.
GetPath(
false));
512 auto error = SendSyncRequest(
kSTAT, remote_file_path.length(),
513 remote_file_path.c_str());
515 return Status(
"Failed to send request: %s",
error.AsCString());
517 static const size_t stat_len = strlen(
kSTAT);
518 static const size_t response_len = stat_len + (
sizeof(uint32_t) * 3);
520 std::vector<char> buffer(response_len);
523 return Status(
"Failed to read response: %s",
error.AsCString());
529 const void *command = extractor.
GetData(&offset, stat_len);
531 return Status(
"Failed to get response command");
532 const char *command_str =
static_cast<const char *
>(command);
533 if (strncmp(command_str,
kSTAT, stat_len))
534 return Status(
"Got invalid stat command: %s", command_str);
536 mode = extractor.
GetU32(&offset);
537 size = extractor.
GetU32(&offset);
538 mtime = extractor.
GetU32(&offset);
544 return executeCommand([
this, &remote_file, &local_file]() {
545 return internalPullFile(remote_file, local_file);
551 return executeCommand([
this, &local_file, &remote_file]() {
552 return internalPushFile(local_file, remote_file);
557 uint32_t &size, uint32_t &mtime) {
558 return executeCommand([
this, &remote_file, &mode, &size, &mtime]() {
559 return internalStat(remote_file, mode, size, mtime);
568 :
m_conn(std::move(conn)) {}
573 return Status(
"SyncService is disconnected");
575 const auto error = cmd();
585 const uint32_t data_len,
588 encoder.
AppendData(llvm::StringRef(request_id));
590 llvm::ArrayRef<uint8_t> bytes = encoder.
GetData();
603 uint32_t &data_len) {
607 if (
error.Success()) {
608 response_id.assign(&buffer[0], 4);
611 data_len = extractor.
GetU32(&offset);
621 std::string response_id;
623 auto error = ReadSyncHeader(response_id, data_len);
627 if (response_id ==
kDATA) {
628 buffer.resize(data_len, 0);
632 }
else if (response_id ==
kDONE) {
634 }
else if (response_id ==
kFAIL) {
635 std::string error_message(data_len, 0);
638 return Status(
"Failed to read pull error message: %s",
error.AsCString());
639 return Status(
"Failed to pull file: %s", error_message.c_str());
641 return Status(
"Pull failed with unknown response: %s", response_id.c_str());
647 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()
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.