Loading adb/client/adb_install.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -290,7 +290,7 @@ static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy) } } if (do_sync_push(apk_file, apk_dest.c_str(), false, true)) { if (do_sync_push(apk_file, apk_dest.c_str(), false, CompressionType::Any)) { result = pm_command(argc, argv); delete_device_file(apk_dest); } Loading adb/client/bugreport.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -282,5 +282,5 @@ int Bugreport::SendShellCommand(const std::string& command, bool disable_shell_p bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs, const char* name) { return do_sync_pull(srcs, dst, copy_attrs, false, name); return do_sync_pull(srcs, dst, copy_attrs, CompressionType::None, name); } adb/client/commandline.cpp +52 −31 Original line number Diff line number Diff line Loading @@ -129,20 +129,20 @@ static void help() { " reverse --remove-all remove all reverse socket connections from device\n" "\n" "file transfer:\n" " push [--sync] [-zZ] LOCAL... REMOTE\n" " push [--sync] [-z ALGORITHM] [-Z] LOCAL... REMOTE\n" " copy local files/directories to device\n" " --sync: only push files that are newer on the host than the device\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" " pull [-azZ] REMOTE... LOCAL\n" " pull [-a] [-z ALGORITHM] [-Z] REMOTE... LOCAL\n" " copy files/dirs from device\n" " -a: preserve file timestamp and mode\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" " sync [-lzZ] [all|data|odm|oem|product|system|system_ext|vendor]\n" " sync [-l] [-z ALGORITHM] [-Z] [all|data|odm|oem|product|system|system_ext|vendor]\n" " sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n" " -l: list files that would be copied, but don't copy them\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" "\n" "shell:\n" Loading Loading @@ -1314,12 +1314,34 @@ static int restore(int argc, const char** argv) { return 0; } static CompressionType parse_compression_type(const std::string& str, bool allow_numbers) { if (allow_numbers) { if (str == "0") { return CompressionType::None; } else if (str == "1") { return CompressionType::Any; } } if (str == "any") { return CompressionType::Any; } else if (str == "none") { return CompressionType::None; } if (str == "brotli") { return CompressionType::Brotli; } error_exit("unexpected compression type %s", str.c_str()); } static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs, const char** dst, bool* copy_attrs, bool* sync, bool* compressed) { const char** dst, bool* copy_attrs, bool* sync, CompressionType* compression) { *copy_attrs = false; const char* adb_compression = getenv("ADB_COMPRESSION"); if (adb_compression && strcmp(adb_compression, "0") == 0) { *compressed = false; if (const char* adb_compression = getenv("ADB_COMPRESSION")) { *compression = parse_compression_type(adb_compression, true); } srcs->clear(); Loading @@ -1333,13 +1355,13 @@ static void parse_push_pull_args(const char** arg, int narg, std::vector<const c } else if (!strcmp(*arg, "-a")) { *copy_attrs = true; } else if (!strcmp(*arg, "-z")) { if (compressed != nullptr) { *compressed = true; if (narg < 2) { error_exit("-z requires an argument"); } *compression = parse_compression_type(*++arg, false); --narg; } else if (!strcmp(*arg, "-Z")) { if (compressed != nullptr) { *compressed = false; } *compression = CompressionType::None; } else if (!strcmp(*arg, "--sync")) { if (sync != nullptr) { *sync = true; Loading Loading @@ -1894,22 +1916,22 @@ int adb_commandline(int argc, const char** argv) { } else if (!strcmp(argv[0], "push")) { bool copy_attrs = false; bool sync = false; bool compressed = true; CompressionType compression = CompressionType::Any; std::vector<const char*> srcs; const char* dst = nullptr; parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compressed); parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compression); if (srcs.empty() || !dst) error_exit("push requires an argument"); return do_sync_push(srcs, dst, sync, compressed) ? 0 : 1; return do_sync_push(srcs, dst, sync, compression) ? 0 : 1; } else if (!strcmp(argv[0], "pull")) { bool copy_attrs = false; bool compressed = true; CompressionType compression = CompressionType::Any; std::vector<const char*> srcs; const char* dst = "."; parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compressed); parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compression); if (srcs.empty()) error_exit("pull requires an argument"); return do_sync_pull(srcs, dst, copy_attrs, compressed) ? 0 : 1; return do_sync_pull(srcs, dst, copy_attrs, compression) ? 0 : 1; } else if (!strcmp(argv[0], "install")) { if (argc < 2) error_exit("install requires an argument"); return install_app(argc, argv); Loading @@ -1925,27 +1947,26 @@ int adb_commandline(int argc, const char** argv) { } else if (!strcmp(argv[0], "sync")) { std::string src; bool list_only = false; bool compressed = true; CompressionType compression = CompressionType::Any; const char* adb_compression = getenv("ADB_COMPRESSION"); if (adb_compression && strcmp(adb_compression, "0") == 0) { compressed = false; if (const char* adb_compression = getenv("ADB_COMPRESSION"); adb_compression) { compression = parse_compression_type(adb_compression, true); } int opt; while ((opt = getopt(argc, const_cast<char**>(argv), "lzZ")) != -1) { while ((opt = getopt(argc, const_cast<char**>(argv), "lz:Z")) != -1) { switch (opt) { case 'l': list_only = true; break; case 'z': compressed = true; compression = parse_compression_type(optarg, false); break; case 'Z': compressed = false; compression = CompressionType::None; break; default: error_exit("usage: adb sync [-lzZ] [PARTITION]"); error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]"); } } Loading @@ -1954,7 +1975,7 @@ int adb_commandline(int argc, const char** argv) { } else if (optind + 1 == argc) { src = argv[optind]; } else { error_exit("usage: adb sync [-lzZ] [PARTITION]"); error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]"); } std::vector<std::string> partitions{"data", "odm", "oem", "product", Loading @@ -1965,7 +1986,7 @@ int adb_commandline(int argc, const char** argv) { std::string src_dir{product_file(partition)}; if (!directory_exists(src_dir)) continue; found = true; if (!do_sync_sync(src_dir, "/" + partition, list_only, compressed)) return 1; if (!do_sync_sync(src_dir, "/" + partition, list_only, compression)) return 1; } } if (!found) error_exit("don't know how to sync %s partition", src.c_str()); Loading adb/client/fastdeploy.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ static void push_to_device(const void* data, size_t byte_count, const char* dst, // but can't be removed until after the push. unix_close(tf.release()); if (!do_sync_push(srcs, dst, sync, true)) { if (!do_sync_push(srcs, dst, sync, CompressionType::Any)) { error_exit("Failed to push fastdeploy agent to device."); } } Loading adb/client/file_sync_client.cpp +128 −74 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <memory> #include <sstream> #include <string> #include <variant> #include <vector> #include "sysdeps.h" Loading Loading @@ -262,6 +263,18 @@ class SyncConnection { bool HaveSendRecv2() const { return have_sendrecv_v2_; } bool HaveSendRecv2Brotli() const { return have_sendrecv_v2_brotli_; } // Resolve a compression type which might be CompressionType::Any to a specific compression // algorithm. CompressionType ResolveCompressionType(CompressionType compression) const { if (compression == CompressionType::Any) { if (HaveSendRecv2Brotli()) { return CompressionType::Brotli; } return CompressionType::None; } return compression; } const FeatureSet& Features() const { return features_; } bool IsValid() { return fd >= 0; } Loading Loading @@ -323,7 +336,7 @@ class SyncConnection { return WriteFdExactly(fd, buf.data(), buf.size()); } bool SendSend2(std::string_view path, mode_t mode, bool compressed) { bool SendSend2(std::string_view path, mode_t mode, CompressionType compression) { if (path.length() > 1024) { Error("SendRequest failed: path too long: %zu", path.length()); errno = ENAMETOOLONG; Loading @@ -339,7 +352,18 @@ class SyncConnection { syncmsg msg; msg.send_v2_setup.id = ID_SEND_V2; msg.send_v2_setup.mode = mode; msg.send_v2_setup.flags = compressed ? kSyncFlagBrotli : kSyncFlagNone; msg.send_v2_setup.flags = 0; switch (compression) { case CompressionType::None: break; case CompressionType::Brotli: msg.send_v2_setup.flags = kSyncFlagBrotli; break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.send_v2_setup)); Loading @@ -352,7 +376,7 @@ class SyncConnection { return WriteFdExactly(fd, buf.data(), buf.size()); } bool SendRecv2(const std::string& path) { bool SendRecv2(const std::string& path, CompressionType compression) { if (path.length() > 1024) { Error("SendRequest failed: path too long: %zu", path.length()); errno = ENAMETOOLONG; Loading @@ -367,7 +391,18 @@ class SyncConnection { syncmsg msg; msg.recv_v2_setup.id = ID_RECV_V2; msg.recv_v2_setup.flags = kSyncFlagBrotli; msg.recv_v2_setup.flags = 0; switch (compression) { case CompressionType::None: break; case CompressionType::Brotli: msg.recv_v2_setup.flags |= kSyncFlagBrotli; break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.recv_v2_setup)); Loading Loading @@ -533,9 +568,15 @@ class SyncConnection { return true; } bool SendLargeFileCompressed(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime) { if (!SendSend2(path, mode, true)) { bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime, CompressionType compression) { if (!HaveSendRecv2()) { return SendLargeFileLegacy(path, mode, lpath, rpath, mtime); } compression = ResolveCompressionType(compression); if (!SendSend2(path, mode, compression)) { Error("failed to send ID_SEND_V2 message '%s': %s", path.c_str(), strerror(errno)); return false; } Loading @@ -558,7 +599,21 @@ class SyncConnection { syncsendbuf sbuf; sbuf.id = ID_DATA; BrotliEncoder<SYNC_DATA_MAX> encoder; std::variant<std::monostate, NullEncoder, BrotliEncoder> encoder_storage; Encoder* encoder = nullptr; switch (compression) { case CompressionType::None: encoder = &encoder_storage.emplace<NullEncoder>(SYNC_DATA_MAX); break; case CompressionType::Brotli: encoder = &encoder_storage.emplace<BrotliEncoder>(SYNC_DATA_MAX); break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } bool sending = true; while (sending) { Block input(SYNC_DATA_MAX); Loading @@ -569,10 +624,10 @@ class SyncConnection { } if (r == 0) { encoder.Finish(); encoder->Finish(); } else { input.resize(r); encoder.Append(std::move(input)); encoder->Append(std::move(input)); RecordBytesTransferred(r); bytes_copied += r; ReportProgress(rpath, bytes_copied, total_size); Loading @@ -580,7 +635,7 @@ class SyncConnection { while (true) { Block output; EncodeResult result = encoder.Encode(&output); EncodeResult result = encoder->Encode(&output); if (result == EncodeResult::Error) { Error("compressing '%s' locally failed", lpath.c_str()); return false; Loading Loading @@ -610,12 +665,8 @@ class SyncConnection { return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data)); } bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime, bool compressed) { if (compressed && HaveSendRecv2Brotli()) { return SendLargeFileCompressed(path, mode, lpath, rpath, mtime); } bool SendLargeFileLegacy(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime) { std::string path_and_mode = android::base::StringPrintf("%s,%d", path.c_str(), mode); if (!SendRequest(ID_SEND_V1, path_and_mode)) { Error("failed to send ID_SEND_V1 message '%s': %s", path_and_mode.c_str(), Loading Loading @@ -921,7 +972,7 @@ static bool sync_stat_fallback(SyncConnection& sc, const std::string& path, stru } static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::string& rpath, unsigned mtime, mode_t mode, bool sync, bool compressed) { unsigned mtime, mode_t mode, bool sync, CompressionType compression) { if (sync) { struct stat st; if (sync_lstat(sc, rpath, &st)) { Loading Loading @@ -964,7 +1015,7 @@ static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::s return false; } } else { if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compressed)) { if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compression)) { return false; } } Loading Loading @@ -1027,8 +1078,10 @@ static bool sync_recv_v1(SyncConnection& sc, const char* rpath, const char* lpat } static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpath, const char* name, uint64_t expected_size) { if (!sc.SendRecv2(rpath)) return false; uint64_t expected_size, CompressionType compression) { compression = sc.ResolveCompressionType(compression); if (!sc.SendRecv2(rpath, compression)) return false; adb_unlink(lpath); unique_fd lfd(adb_creat(lpath, 0644)); Loading @@ -1040,9 +1093,24 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat uint64_t bytes_copied = 0; Block buffer(SYNC_DATA_MAX); BrotliDecoder decoder(std::span(buffer.data(), buffer.size())); bool reading = true; while (reading) { std::variant<std::monostate, NullDecoder, BrotliDecoder> decoder_storage; Decoder* decoder = nullptr; std::span buffer_span(buffer.data(), buffer.size()); switch (compression) { case CompressionType::None: decoder = &decoder_storage.emplace<NullDecoder>(buffer_span); break; case CompressionType::Brotli: decoder = &decoder_storage.emplace<BrotliDecoder>(buffer_span); break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } while (true) { syncmsg msg; if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { adb_unlink(lpath); Loading @@ -1050,17 +1118,15 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat } if (msg.data.id == ID_DONE) { adb_unlink(lpath); if (!decoder->Finish()) { sc.Error("unexpected ID_DONE"); return false; } if (msg.data.id != ID_DATA) { } else if (msg.data.id != ID_DATA) { adb_unlink(lpath); sc.ReportCopyFailure(rpath, lpath, msg); return false; } } else { if (msg.data.size > sc.max) { sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max); adb_unlink(lpath); Loading @@ -1072,11 +1138,12 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat adb_unlink(lpath); return false; } decoder.Append(std::move(block)); decoder->Append(std::move(block)); } while (true) { std::span<char> output; DecodeResult result = decoder.Decode(&output); DecodeResult result = decoder->Decode(&output); if (result == DecodeResult::Error) { sc.Error("decompress failed"); Loading @@ -1102,33 +1169,19 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat } else if (result == DecodeResult::MoreOutput) { continue; } else if (result == DecodeResult::Done) { reading = false; break; sc.RecordFilesTransferred(1); return true; } else { LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result); } } } syncmsg msg; if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { sc.Error("failed to read ID_DONE"); return false; } if (msg.data.id != ID_DONE) { sc.Error("unexpected message after transfer: id = %d (expected ID_DONE)", msg.data.id); return false; } sc.RecordFilesTransferred(1); return true; } static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, const char* name, uint64_t expected_size, bool compressed) { if (sc.HaveSendRecv2() && compressed) { return sync_recv_v2(sc, rpath, lpath, name, expected_size); uint64_t expected_size, CompressionType compression) { if (sc.HaveSendRecv2()) { return sync_recv_v2(sc, rpath, lpath, name, expected_size, compression); } else { return sync_recv_v1(sc, rpath, lpath, name, expected_size); } Loading Loading @@ -1210,7 +1263,8 @@ static bool is_root_dir(std::string_view path) { } static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::string rpath, bool check_timestamps, bool list_only, bool compressed) { bool check_timestamps, bool list_only, CompressionType compression) { sc.NewTransfer(); // Make sure that both directory paths end in a slash. Loading Loading @@ -1292,7 +1346,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::st if (list_only) { sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str()); } else { if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compressed)) { if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compression)) { return false; } } Loading @@ -1308,7 +1362,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::st } bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync, bool compressed) { CompressionType compression) { SyncConnection sc; if (!sc.IsValid()) return false; Loading Loading @@ -1373,7 +1427,7 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sy dst_dir.append(android::base::Basename(src_path)); } success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compressed); success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compression); continue; } else if (!should_push_file(st.st_mode)) { sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode); Loading @@ -1394,7 +1448,7 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sy sc.NewTransfer(); sc.SetExpectedTotalBytes(st.st_size); success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compressed); success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compression); sc.ReportTransferRate(src_path, TransferDirection::push); } Loading Loading @@ -1480,7 +1534,7 @@ static int set_time_and_mode(const std::string& lpath, time_t time, } static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::string lpath, bool copy_attrs, bool compressed) { bool copy_attrs, CompressionType compression) { sc.NewTransfer(); // Make sure that both directory paths end in a slash. Loading Loading @@ -1510,7 +1564,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::st continue; } if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compressed)) { if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compression)) { return false; } Loading @@ -1528,7 +1582,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::st } bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs, bool compressed, const char* name) { CompressionType compression, const char* name) { SyncConnection sc; if (!sc.IsValid()) return false; Loading Loading @@ -1602,7 +1656,7 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co dst_dir.append(android::base::Basename(src_path)); } success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compressed); success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compression); continue; } else if (!should_pull_file(src_st.st_mode)) { sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode); Loading @@ -1621,7 +1675,7 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co sc.NewTransfer(); sc.SetExpectedTotalBytes(src_st.st_size); if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compressed)) { if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compression)) { success = false; continue; } Loading @@ -1638,11 +1692,11 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co } bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only, bool compressed) { CompressionType compression) { SyncConnection sc; if (!sc.IsValid()) return false; bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compressed); bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compression); if (!list_only) { sc.ReportOverallTransferRate(TransferDirection::push); } Loading Loading
adb/client/adb_install.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -290,7 +290,7 @@ static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy) } } if (do_sync_push(apk_file, apk_dest.c_str(), false, true)) { if (do_sync_push(apk_file, apk_dest.c_str(), false, CompressionType::Any)) { result = pm_command(argc, argv); delete_device_file(apk_dest); } Loading
adb/client/bugreport.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -282,5 +282,5 @@ int Bugreport::SendShellCommand(const std::string& command, bool disable_shell_p bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs, const char* name) { return do_sync_pull(srcs, dst, copy_attrs, false, name); return do_sync_pull(srcs, dst, copy_attrs, CompressionType::None, name); }
adb/client/commandline.cpp +52 −31 Original line number Diff line number Diff line Loading @@ -129,20 +129,20 @@ static void help() { " reverse --remove-all remove all reverse socket connections from device\n" "\n" "file transfer:\n" " push [--sync] [-zZ] LOCAL... REMOTE\n" " push [--sync] [-z ALGORITHM] [-Z] LOCAL... REMOTE\n" " copy local files/directories to device\n" " --sync: only push files that are newer on the host than the device\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" " pull [-azZ] REMOTE... LOCAL\n" " pull [-a] [-z ALGORITHM] [-Z] REMOTE... LOCAL\n" " copy files/dirs from device\n" " -a: preserve file timestamp and mode\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" " sync [-lzZ] [all|data|odm|oem|product|system|system_ext|vendor]\n" " sync [-l] [-z ALGORITHM] [-Z] [all|data|odm|oem|product|system|system_ext|vendor]\n" " sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n" " -l: list files that would be copied, but don't copy them\n" " -z: enable compression\n" " -z: enable compression with a specified algorithm (any, none, brotli)\n" " -Z: disable compression\n" "\n" "shell:\n" Loading Loading @@ -1314,12 +1314,34 @@ static int restore(int argc, const char** argv) { return 0; } static CompressionType parse_compression_type(const std::string& str, bool allow_numbers) { if (allow_numbers) { if (str == "0") { return CompressionType::None; } else if (str == "1") { return CompressionType::Any; } } if (str == "any") { return CompressionType::Any; } else if (str == "none") { return CompressionType::None; } if (str == "brotli") { return CompressionType::Brotli; } error_exit("unexpected compression type %s", str.c_str()); } static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs, const char** dst, bool* copy_attrs, bool* sync, bool* compressed) { const char** dst, bool* copy_attrs, bool* sync, CompressionType* compression) { *copy_attrs = false; const char* adb_compression = getenv("ADB_COMPRESSION"); if (adb_compression && strcmp(adb_compression, "0") == 0) { *compressed = false; if (const char* adb_compression = getenv("ADB_COMPRESSION")) { *compression = parse_compression_type(adb_compression, true); } srcs->clear(); Loading @@ -1333,13 +1355,13 @@ static void parse_push_pull_args(const char** arg, int narg, std::vector<const c } else if (!strcmp(*arg, "-a")) { *copy_attrs = true; } else if (!strcmp(*arg, "-z")) { if (compressed != nullptr) { *compressed = true; if (narg < 2) { error_exit("-z requires an argument"); } *compression = parse_compression_type(*++arg, false); --narg; } else if (!strcmp(*arg, "-Z")) { if (compressed != nullptr) { *compressed = false; } *compression = CompressionType::None; } else if (!strcmp(*arg, "--sync")) { if (sync != nullptr) { *sync = true; Loading Loading @@ -1894,22 +1916,22 @@ int adb_commandline(int argc, const char** argv) { } else if (!strcmp(argv[0], "push")) { bool copy_attrs = false; bool sync = false; bool compressed = true; CompressionType compression = CompressionType::Any; std::vector<const char*> srcs; const char* dst = nullptr; parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compressed); parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compression); if (srcs.empty() || !dst) error_exit("push requires an argument"); return do_sync_push(srcs, dst, sync, compressed) ? 0 : 1; return do_sync_push(srcs, dst, sync, compression) ? 0 : 1; } else if (!strcmp(argv[0], "pull")) { bool copy_attrs = false; bool compressed = true; CompressionType compression = CompressionType::Any; std::vector<const char*> srcs; const char* dst = "."; parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compressed); parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compression); if (srcs.empty()) error_exit("pull requires an argument"); return do_sync_pull(srcs, dst, copy_attrs, compressed) ? 0 : 1; return do_sync_pull(srcs, dst, copy_attrs, compression) ? 0 : 1; } else if (!strcmp(argv[0], "install")) { if (argc < 2) error_exit("install requires an argument"); return install_app(argc, argv); Loading @@ -1925,27 +1947,26 @@ int adb_commandline(int argc, const char** argv) { } else if (!strcmp(argv[0], "sync")) { std::string src; bool list_only = false; bool compressed = true; CompressionType compression = CompressionType::Any; const char* adb_compression = getenv("ADB_COMPRESSION"); if (adb_compression && strcmp(adb_compression, "0") == 0) { compressed = false; if (const char* adb_compression = getenv("ADB_COMPRESSION"); adb_compression) { compression = parse_compression_type(adb_compression, true); } int opt; while ((opt = getopt(argc, const_cast<char**>(argv), "lzZ")) != -1) { while ((opt = getopt(argc, const_cast<char**>(argv), "lz:Z")) != -1) { switch (opt) { case 'l': list_only = true; break; case 'z': compressed = true; compression = parse_compression_type(optarg, false); break; case 'Z': compressed = false; compression = CompressionType::None; break; default: error_exit("usage: adb sync [-lzZ] [PARTITION]"); error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]"); } } Loading @@ -1954,7 +1975,7 @@ int adb_commandline(int argc, const char** argv) { } else if (optind + 1 == argc) { src = argv[optind]; } else { error_exit("usage: adb sync [-lzZ] [PARTITION]"); error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]"); } std::vector<std::string> partitions{"data", "odm", "oem", "product", Loading @@ -1965,7 +1986,7 @@ int adb_commandline(int argc, const char** argv) { std::string src_dir{product_file(partition)}; if (!directory_exists(src_dir)) continue; found = true; if (!do_sync_sync(src_dir, "/" + partition, list_only, compressed)) return 1; if (!do_sync_sync(src_dir, "/" + partition, list_only, compression)) return 1; } } if (!found) error_exit("don't know how to sync %s partition", src.c_str()); Loading
adb/client/fastdeploy.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ static void push_to_device(const void* data, size_t byte_count, const char* dst, // but can't be removed until after the push. unix_close(tf.release()); if (!do_sync_push(srcs, dst, sync, true)) { if (!do_sync_push(srcs, dst, sync, CompressionType::Any)) { error_exit("Failed to push fastdeploy agent to device."); } } Loading
adb/client/file_sync_client.cpp +128 −74 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <memory> #include <sstream> #include <string> #include <variant> #include <vector> #include "sysdeps.h" Loading Loading @@ -262,6 +263,18 @@ class SyncConnection { bool HaveSendRecv2() const { return have_sendrecv_v2_; } bool HaveSendRecv2Brotli() const { return have_sendrecv_v2_brotli_; } // Resolve a compression type which might be CompressionType::Any to a specific compression // algorithm. CompressionType ResolveCompressionType(CompressionType compression) const { if (compression == CompressionType::Any) { if (HaveSendRecv2Brotli()) { return CompressionType::Brotli; } return CompressionType::None; } return compression; } const FeatureSet& Features() const { return features_; } bool IsValid() { return fd >= 0; } Loading Loading @@ -323,7 +336,7 @@ class SyncConnection { return WriteFdExactly(fd, buf.data(), buf.size()); } bool SendSend2(std::string_view path, mode_t mode, bool compressed) { bool SendSend2(std::string_view path, mode_t mode, CompressionType compression) { if (path.length() > 1024) { Error("SendRequest failed: path too long: %zu", path.length()); errno = ENAMETOOLONG; Loading @@ -339,7 +352,18 @@ class SyncConnection { syncmsg msg; msg.send_v2_setup.id = ID_SEND_V2; msg.send_v2_setup.mode = mode; msg.send_v2_setup.flags = compressed ? kSyncFlagBrotli : kSyncFlagNone; msg.send_v2_setup.flags = 0; switch (compression) { case CompressionType::None: break; case CompressionType::Brotli: msg.send_v2_setup.flags = kSyncFlagBrotli; break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.send_v2_setup)); Loading @@ -352,7 +376,7 @@ class SyncConnection { return WriteFdExactly(fd, buf.data(), buf.size()); } bool SendRecv2(const std::string& path) { bool SendRecv2(const std::string& path, CompressionType compression) { if (path.length() > 1024) { Error("SendRequest failed: path too long: %zu", path.length()); errno = ENAMETOOLONG; Loading @@ -367,7 +391,18 @@ class SyncConnection { syncmsg msg; msg.recv_v2_setup.id = ID_RECV_V2; msg.recv_v2_setup.flags = kSyncFlagBrotli; msg.recv_v2_setup.flags = 0; switch (compression) { case CompressionType::None: break; case CompressionType::Brotli: msg.recv_v2_setup.flags |= kSyncFlagBrotli; break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.recv_v2_setup)); Loading Loading @@ -533,9 +568,15 @@ class SyncConnection { return true; } bool SendLargeFileCompressed(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime) { if (!SendSend2(path, mode, true)) { bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime, CompressionType compression) { if (!HaveSendRecv2()) { return SendLargeFileLegacy(path, mode, lpath, rpath, mtime); } compression = ResolveCompressionType(compression); if (!SendSend2(path, mode, compression)) { Error("failed to send ID_SEND_V2 message '%s': %s", path.c_str(), strerror(errno)); return false; } Loading @@ -558,7 +599,21 @@ class SyncConnection { syncsendbuf sbuf; sbuf.id = ID_DATA; BrotliEncoder<SYNC_DATA_MAX> encoder; std::variant<std::monostate, NullEncoder, BrotliEncoder> encoder_storage; Encoder* encoder = nullptr; switch (compression) { case CompressionType::None: encoder = &encoder_storage.emplace<NullEncoder>(SYNC_DATA_MAX); break; case CompressionType::Brotli: encoder = &encoder_storage.emplace<BrotliEncoder>(SYNC_DATA_MAX); break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } bool sending = true; while (sending) { Block input(SYNC_DATA_MAX); Loading @@ -569,10 +624,10 @@ class SyncConnection { } if (r == 0) { encoder.Finish(); encoder->Finish(); } else { input.resize(r); encoder.Append(std::move(input)); encoder->Append(std::move(input)); RecordBytesTransferred(r); bytes_copied += r; ReportProgress(rpath, bytes_copied, total_size); Loading @@ -580,7 +635,7 @@ class SyncConnection { while (true) { Block output; EncodeResult result = encoder.Encode(&output); EncodeResult result = encoder->Encode(&output); if (result == EncodeResult::Error) { Error("compressing '%s' locally failed", lpath.c_str()); return false; Loading Loading @@ -610,12 +665,8 @@ class SyncConnection { return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data)); } bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime, bool compressed) { if (compressed && HaveSendRecv2Brotli()) { return SendLargeFileCompressed(path, mode, lpath, rpath, mtime); } bool SendLargeFileLegacy(const std::string& path, mode_t mode, const std::string& lpath, const std::string& rpath, unsigned mtime) { std::string path_and_mode = android::base::StringPrintf("%s,%d", path.c_str(), mode); if (!SendRequest(ID_SEND_V1, path_and_mode)) { Error("failed to send ID_SEND_V1 message '%s': %s", path_and_mode.c_str(), Loading Loading @@ -921,7 +972,7 @@ static bool sync_stat_fallback(SyncConnection& sc, const std::string& path, stru } static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::string& rpath, unsigned mtime, mode_t mode, bool sync, bool compressed) { unsigned mtime, mode_t mode, bool sync, CompressionType compression) { if (sync) { struct stat st; if (sync_lstat(sc, rpath, &st)) { Loading Loading @@ -964,7 +1015,7 @@ static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::s return false; } } else { if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compressed)) { if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compression)) { return false; } } Loading Loading @@ -1027,8 +1078,10 @@ static bool sync_recv_v1(SyncConnection& sc, const char* rpath, const char* lpat } static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpath, const char* name, uint64_t expected_size) { if (!sc.SendRecv2(rpath)) return false; uint64_t expected_size, CompressionType compression) { compression = sc.ResolveCompressionType(compression); if (!sc.SendRecv2(rpath, compression)) return false; adb_unlink(lpath); unique_fd lfd(adb_creat(lpath, 0644)); Loading @@ -1040,9 +1093,24 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat uint64_t bytes_copied = 0; Block buffer(SYNC_DATA_MAX); BrotliDecoder decoder(std::span(buffer.data(), buffer.size())); bool reading = true; while (reading) { std::variant<std::monostate, NullDecoder, BrotliDecoder> decoder_storage; Decoder* decoder = nullptr; std::span buffer_span(buffer.data(), buffer.size()); switch (compression) { case CompressionType::None: decoder = &decoder_storage.emplace<NullDecoder>(buffer_span); break; case CompressionType::Brotli: decoder = &decoder_storage.emplace<BrotliDecoder>(buffer_span); break; case CompressionType::Any: LOG(FATAL) << "unexpected CompressionType::Any"; } while (true) { syncmsg msg; if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { adb_unlink(lpath); Loading @@ -1050,17 +1118,15 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat } if (msg.data.id == ID_DONE) { adb_unlink(lpath); if (!decoder->Finish()) { sc.Error("unexpected ID_DONE"); return false; } if (msg.data.id != ID_DATA) { } else if (msg.data.id != ID_DATA) { adb_unlink(lpath); sc.ReportCopyFailure(rpath, lpath, msg); return false; } } else { if (msg.data.size > sc.max) { sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max); adb_unlink(lpath); Loading @@ -1072,11 +1138,12 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat adb_unlink(lpath); return false; } decoder.Append(std::move(block)); decoder->Append(std::move(block)); } while (true) { std::span<char> output; DecodeResult result = decoder.Decode(&output); DecodeResult result = decoder->Decode(&output); if (result == DecodeResult::Error) { sc.Error("decompress failed"); Loading @@ -1102,33 +1169,19 @@ static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpat } else if (result == DecodeResult::MoreOutput) { continue; } else if (result == DecodeResult::Done) { reading = false; break; sc.RecordFilesTransferred(1); return true; } else { LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result); } } } syncmsg msg; if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { sc.Error("failed to read ID_DONE"); return false; } if (msg.data.id != ID_DONE) { sc.Error("unexpected message after transfer: id = %d (expected ID_DONE)", msg.data.id); return false; } sc.RecordFilesTransferred(1); return true; } static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, const char* name, uint64_t expected_size, bool compressed) { if (sc.HaveSendRecv2() && compressed) { return sync_recv_v2(sc, rpath, lpath, name, expected_size); uint64_t expected_size, CompressionType compression) { if (sc.HaveSendRecv2()) { return sync_recv_v2(sc, rpath, lpath, name, expected_size, compression); } else { return sync_recv_v1(sc, rpath, lpath, name, expected_size); } Loading Loading @@ -1210,7 +1263,8 @@ static bool is_root_dir(std::string_view path) { } static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::string rpath, bool check_timestamps, bool list_only, bool compressed) { bool check_timestamps, bool list_only, CompressionType compression) { sc.NewTransfer(); // Make sure that both directory paths end in a slash. Loading Loading @@ -1292,7 +1346,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::st if (list_only) { sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str()); } else { if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compressed)) { if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compression)) { return false; } } Loading @@ -1308,7 +1362,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::st } bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync, bool compressed) { CompressionType compression) { SyncConnection sc; if (!sc.IsValid()) return false; Loading Loading @@ -1373,7 +1427,7 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sy dst_dir.append(android::base::Basename(src_path)); } success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compressed); success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compression); continue; } else if (!should_push_file(st.st_mode)) { sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode); Loading @@ -1394,7 +1448,7 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sy sc.NewTransfer(); sc.SetExpectedTotalBytes(st.st_size); success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compressed); success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compression); sc.ReportTransferRate(src_path, TransferDirection::push); } Loading Loading @@ -1480,7 +1534,7 @@ static int set_time_and_mode(const std::string& lpath, time_t time, } static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::string lpath, bool copy_attrs, bool compressed) { bool copy_attrs, CompressionType compression) { sc.NewTransfer(); // Make sure that both directory paths end in a slash. Loading Loading @@ -1510,7 +1564,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::st continue; } if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compressed)) { if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compression)) { return false; } Loading @@ -1528,7 +1582,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::st } bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs, bool compressed, const char* name) { CompressionType compression, const char* name) { SyncConnection sc; if (!sc.IsValid()) return false; Loading Loading @@ -1602,7 +1656,7 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co dst_dir.append(android::base::Basename(src_path)); } success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compressed); success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compression); continue; } else if (!should_pull_file(src_st.st_mode)) { sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode); Loading @@ -1621,7 +1675,7 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co sc.NewTransfer(); sc.SetExpectedTotalBytes(src_st.st_size); if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compressed)) { if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compression)) { success = false; continue; } Loading @@ -1638,11 +1692,11 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co } bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only, bool compressed) { CompressionType compression) { SyncConnection sc; if (!sc.IsValid()) return false; bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compressed); bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compression); if (!list_only) { sc.ReportOverallTransferRate(TransferDirection::push); } Loading