Merge "[adb] Print fewer progress messages for push/pull" into rvc-dev
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 14ccfbe..2199fd3 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1423,13 +1423,13 @@
#endif
}
-static bool _is_valid_fd(int fd) {
+static bool _is_valid_os_fd(int fd) {
// Disallow invalid FDs and stdin/out/err as well.
if (fd < 3) {
return false;
}
#ifdef _WIN32
- HANDLE handle = adb_get_os_handle(fd);
+ auto handle = (HANDLE)fd;
DWORD info = 0;
if (GetHandleInformation(handle, &info) == 0) {
return false;
@@ -2005,7 +2005,7 @@
#endif
}
int connection_fd = atoi(argv[1]);
- if (!_is_valid_fd(connection_fd)) {
+ if (!_is_valid_os_fd(connection_fd)) {
error_exit("Invalid connection_fd number given: %d", connection_fd);
}
@@ -2013,7 +2013,7 @@
close_on_exec(connection_fd);
int output_fd = atoi(argv[2]);
- if (!_is_valid_fd(output_fd)) {
+ if (!_is_valid_os_fd(output_fd)) {
error_exit("Invalid output_fd number given: %d", output_fd);
}
output_fd = adb_register_socket(output_fd);
diff --git a/adb/client/incremental.cpp b/adb/client/incremental.cpp
index fd608cc..a9e65dc 100644
--- a/adb/client/incremental.cpp
+++ b/adb/client/incremental.cpp
@@ -41,8 +41,7 @@
static inline int32_t read_int32(borrowed_fd fd) {
int32_t result;
- ReadFully(fd, &result, sizeof(result));
- return result;
+ return ReadFdExactly(fd, &result, sizeof(result)) ? result : -1;
}
static inline void append_int(borrowed_fd fd, std::vector<char>* bytes) {
@@ -54,11 +53,14 @@
static inline void append_bytes_with_size(borrowed_fd fd, std::vector<char>* bytes) {
int32_t le_size = read_int32(fd);
+ if (le_size < 0) {
+ return;
+ }
int32_t size = int32_t(le32toh(le_size));
auto old_size = bytes->size();
bytes->resize(old_size + sizeof(le_size) + size);
memcpy(bytes->data() + old_size, &le_size, sizeof(le_size));
- ReadFully(fd, bytes->data() + old_size + sizeof(le_size), size);
+ ReadFdExactly(fd, bytes->data() + old_size + sizeof(le_size), size);
}
static inline std::pair<std::vector<char>, int32_t> read_id_sig_headers(borrowed_fd fd) {
@@ -200,7 +202,7 @@
return {};
}
auto [pipe_read_fd, pipe_write_fd] = print_fds;
- auto pipe_write_fd_param = std::to_string(pipe_write_fd);
+ auto pipe_write_fd_param = std::to_string(intptr_t(adb_get_os_handle(pipe_write_fd)));
close_on_exec(pipe_read_fd);
std::vector<std::string> args(std::move(files));
diff --git a/adb/client/incremental_server.cpp b/adb/client/incremental_server.cpp
index 1f47de8..737563c 100644
--- a/adb/client/incremental_server.cpp
+++ b/adb/client/incremental_server.cpp
@@ -228,7 +228,7 @@
std::vector<char> pendingBlocks_;
// True when client notifies that all the data has been received
- bool servingComplete_;
+ bool servingComplete_ = false;
};
bool IncrementalServer::SkipToRequest(void* buffer, size_t* size, bool blocking) {
diff --git a/adb/client/incremental_utils.cpp b/adb/client/incremental_utils.cpp
index 316480c..caadb26 100644
--- a/adb/client/incremental_utils.cpp
+++ b/adb/client/incremental_utils.cpp
@@ -18,6 +18,7 @@
#include "incremental_utils.h"
+#include <android-base/mapped_file.h>
#include <android-base/strings.h>
#include <ziparchive/zip_archive.h>
#include <ziparchive/zip_writer.h>
@@ -26,6 +27,7 @@
#include <numeric>
#include <unordered_set>
+#include "adb_trace.h"
#include "sysdeps.h"
static constexpr int kBlockSize = 4096;
@@ -155,18 +157,81 @@
return zipPriorityBlocks;
}
-// TODO(b/151676293): avoid using OpenArchiveFd that reads local file headers
+[[maybe_unused]] static ZipArchiveHandle openZipArchiveFd(int fd) {
+ bool transferFdOwnership = false;
+#ifdef _WIN32
+ //
+ // Need to create a special CRT FD here as the current one is not compatible with
+ // normal read()/write() calls that libziparchive uses.
+ // To make this work we have to create a copy of the file handle, as CRT doesn't care
+ // and closes it together with the new descriptor.
+ //
+ // Note: don't move this into a helper function, it's better to be hard to reuse because
+ // the code is ugly and won't work unless it's a last resort.
+ //
+ auto handle = adb_get_os_handle(fd);
+ HANDLE dupedHandle;
+ if (!::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(), &dupedHandle, 0,
+ false, DUPLICATE_SAME_ACCESS)) {
+ D("%s failed at DuplicateHandle: %d", __func__, (int)::GetLastError());
+ return {};
+ }
+ fd = _open_osfhandle((intptr_t)dupedHandle, _O_RDONLY | _O_BINARY);
+ if (fd < 0) {
+ D("%s failed at _open_osfhandle: %d", __func__, errno);
+ ::CloseHandle(handle);
+ return {};
+ }
+ transferFdOwnership = true;
+#endif
+ ZipArchiveHandle zip;
+ if (OpenArchiveFd(fd, "apk_fd", &zip, transferFdOwnership) != 0) {
+ D("%s failed at OpenArchiveFd: %d", __func__, errno);
+#ifdef _WIN32
+ // "_close()" is a secret WinCRT name for the regular close() function.
+ _close(fd);
+#endif
+ return {};
+ }
+ return zip;
+}
+
+static std::pair<ZipArchiveHandle, std::unique_ptr<android::base::MappedFile>> openZipArchive(
+ int fd, int64_t fileSize) {
+#ifndef __LP64__
+ if (fileSize >= INT_MAX) {
+ return {openZipArchiveFd(fd), nullptr};
+ }
+#endif
+ auto mapping =
+ android::base::MappedFile::FromOsHandle(adb_get_os_handle(fd), 0, fileSize, PROT_READ);
+ if (!mapping) {
+ D("%s failed at FromOsHandle: %d", __func__, errno);
+ return {};
+ }
+ ZipArchiveHandle zip;
+ if (OpenArchiveFromMemory(mapping->data(), mapping->size(), "apk_mapping", &zip) != 0) {
+ D("%s failed at OpenArchiveFromMemory: %d", __func__, errno);
+ return {};
+ }
+ return {zip, std::move(mapping)};
+}
+
+// TODO(b/151676293): avoid using libziparchive as it reads local file headers
// which causes additional performance cost. Instead, only read from central directory.
static std::vector<int32_t> InstallationPriorityBlocks(int fd, int64_t fileSize) {
- std::vector<int32_t> installationPriorityBlocks;
- ZipArchiveHandle zip;
- if (OpenArchiveFd(fd, "", &zip, false) != 0) {
+ auto [zip, _] = openZipArchive(fd, fileSize);
+ if (!zip) {
return {};
}
+
void* cookie = nullptr;
if (StartIteration(zip, &cookie) != 0) {
+ D("%s failed at StartIteration: %d", __func__, errno);
return {};
}
+
+ std::vector<int32_t> installationPriorityBlocks;
ZipEntry entry;
std::string_view entryName;
while (Next(cookie, &entry, &entryName) == 0) {
@@ -183,6 +248,7 @@
int32_t endBlockIndex = offsetToBlockIndex(entryEndOffset);
int32_t numNewBlocks = endBlockIndex - startBlockIndex + 1;
appendBlocks(startBlockIndex, numNewBlocks, &installationPriorityBlocks);
+ D("\tadding to priority blocks: '%.*s'", (int)entryName.size(), entryName.data());
} else if (entryName == "classes.dex") {
// Only the head is needed for installation
int32_t startBlockIndex = offsetToBlockIndex(entry.offset);
@@ -213,4 +279,4 @@
unduplicate(priorityBlocks);
return priorityBlocks;
}
-} // namespace incremental
\ No newline at end of file
+} // namespace incremental
diff --git a/adb/fdevent/fdevent.cpp b/adb/fdevent/fdevent.cpp
index 562f587..fd55020 100644
--- a/adb/fdevent/fdevent.cpp
+++ b/adb/fdevent/fdevent.cpp
@@ -63,7 +63,10 @@
int fd_num = fd.get();
- fdevent* fde = new fdevent();
+ auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fdevent{});
+ CHECK(inserted);
+
+ fdevent* fde = &it->second;
fde->id = fdevent_id_++;
fde->state = 0;
fde->fd = std::move(fd);
@@ -76,10 +79,6 @@
LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get();
}
- auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fde);
- CHECK(inserted);
- UNUSED(it);
-
this->Register(fde);
return fde;
}
@@ -92,12 +91,12 @@
this->Unregister(fde);
- auto erased = this->installed_fdevents_.erase(fde->fd.get());
+ unique_fd fd = std::move(fde->fd);
+
+ auto erased = this->installed_fdevents_.erase(fd.get());
CHECK_EQ(1UL, erased);
- unique_fd result = std::move(fde->fd);
- delete fde;
- return result;
+ return fd;
}
void fdevent_context::Add(fdevent* fde, unsigned events) {
@@ -123,9 +122,9 @@
for (const auto& [fd, fde] : this->installed_fdevents_) {
UNUSED(fd);
- auto timeout_opt = fde->timeout;
+ auto timeout_opt = fde.timeout;
if (timeout_opt) {
- auto deadline = fde->last_active + *timeout_opt;
+ auto deadline = fde.last_active + *timeout_opt;
auto time_left = duration_cast<std::chrono::milliseconds>(deadline - now);
if (time_left < 0ms) {
time_left = 0ms;
@@ -194,11 +193,13 @@
#endif
}
-static auto& g_ambient_fdevent_context =
- *new std::unique_ptr<fdevent_context>(fdevent_create_context());
+static auto& g_ambient_fdevent_context() {
+ static auto context = fdevent_create_context().release();
+ return context;
+}
static fdevent_context* fdevent_get_ambient() {
- return g_ambient_fdevent_context.get();
+ return g_ambient_fdevent_context();
}
fdevent* fdevent_create(int fd, fd_func func, void* arg) {
@@ -256,5 +257,6 @@
}
void fdevent_reset() {
- g_ambient_fdevent_context = fdevent_create_context();
+ auto old = std::exchange(g_ambient_fdevent_context(), fdevent_create_context().release());
+ delete old;
}
diff --git a/adb/fdevent/fdevent.h b/adb/fdevent/fdevent.h
index 86814d7..9fc3b2c 100644
--- a/adb/fdevent/fdevent.h
+++ b/adb/fdevent/fdevent.h
@@ -52,6 +52,20 @@
unsigned events;
};
+struct fdevent final {
+ uint64_t id;
+
+ unique_fd fd;
+ int force_eof = 0;
+
+ uint16_t state = 0;
+ std::optional<std::chrono::milliseconds> timeout;
+ std::chrono::steady_clock::time_point last_active;
+
+ std::variant<fd_func, fd_func2> func;
+ void* arg = nullptr;
+};
+
struct fdevent_context {
public:
virtual ~fdevent_context() = default;
@@ -113,7 +127,7 @@
std::atomic<bool> terminate_loop_ = false;
protected:
- std::unordered_map<int, fdevent*> installed_fdevents_;
+ std::unordered_map<int, fdevent> installed_fdevents_;
private:
uint64_t fdevent_id_ = 0;
@@ -121,20 +135,6 @@
std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_);
};
-struct fdevent {
- uint64_t id;
-
- unique_fd fd;
- int force_eof = 0;
-
- uint16_t state = 0;
- std::optional<std::chrono::milliseconds> timeout;
- std::chrono::steady_clock::time_point last_active;
-
- std::variant<fd_func, fd_func2> func;
- void* arg = nullptr;
-};
-
// Backwards compatibility shims that forward to the global fdevent_context.
fdevent* fdevent_create(int fd, fd_func func, void* arg);
fdevent* fdevent_create(int fd, fd_func2 func, void* arg);
diff --git a/adb/fdevent/fdevent_epoll.cpp b/adb/fdevent/fdevent_epoll.cpp
index e3d1674..4ef41d1 100644
--- a/adb/fdevent/fdevent_epoll.cpp
+++ b/adb/fdevent/fdevent_epoll.cpp
@@ -155,15 +155,15 @@
event_map[fde] = events;
}
- for (const auto& [fd, fde] : installed_fdevents_) {
+ for (auto& [fd, fde] : installed_fdevents_) {
unsigned events = 0;
- if (auto it = event_map.find(fde); it != event_map.end()) {
+ if (auto it = event_map.find(&fde); it != event_map.end()) {
events = it->second;
}
if (events == 0) {
- if (fde->timeout) {
- auto deadline = fde->last_active + *fde->timeout;
+ if (fde.timeout) {
+ auto deadline = fde.last_active + *fde.timeout;
if (deadline < post_poll) {
events |= FDE_TIMEOUT;
}
@@ -171,13 +171,13 @@
}
if (events != 0) {
- LOG(DEBUG) << dump_fde(fde) << " got events " << std::hex << std::showbase
+ LOG(DEBUG) << dump_fde(&fde) << " got events " << std::hex << std::showbase
<< events;
- fde_events.push_back({fde, events});
- fde->last_active = post_poll;
+ fde_events.push_back({&fde, events});
+ fde.last_active = post_poll;
}
}
- this->HandleEvents(std::move(fde_events));
+ this->HandleEvents(fde_events);
fde_events.clear();
}
diff --git a/adb/fdevent/fdevent_epoll.h b/adb/fdevent/fdevent_epoll.h
index 684fa32..6214d2e 100644
--- a/adb/fdevent/fdevent_epoll.h
+++ b/adb/fdevent/fdevent_epoll.h
@@ -47,12 +47,7 @@
protected:
virtual void Interrupt() final;
- public:
- // All operations to fdevent should happen only in the main thread.
- // That's why we don't need a lock for fdevent.
- std::unordered_map<int, fdevent*> epoll_node_map_;
- std::list<fdevent*> pending_list_;
-
+ private:
unique_fd epoll_fd_;
unique_fd interrupt_fd_;
fdevent* interrupt_fde_ = nullptr;
diff --git a/adb/fdevent/fdevent_poll.cpp b/adb/fdevent/fdevent_poll.cpp
index cc4a7a1..ac86c08 100644
--- a/adb/fdevent/fdevent_poll.cpp
+++ b/adb/fdevent/fdevent_poll.cpp
@@ -103,24 +103,27 @@
void fdevent_context_poll::Loop() {
main_thread_id_ = android::base::GetThreadId();
+ std::vector<adb_pollfd> pollfds;
+ std::vector<fdevent_event> poll_events;
+
while (true) {
if (terminate_loop_) {
break;
}
D("--- --- waiting for events");
- std::vector<adb_pollfd> pollfds;
+ pollfds.clear();
for (const auto& [fd, fde] : this->installed_fdevents_) {
adb_pollfd pfd;
pfd.fd = fd;
pfd.events = 0;
- if (fde->state & FDE_READ) {
+ if (fde.state & FDE_READ) {
pfd.events |= POLLIN;
}
- if (fde->state & FDE_WRITE) {
+ if (fde.state & FDE_WRITE) {
pfd.events |= POLLOUT;
}
- if (fde->state & FDE_ERROR) {
+ if (fde.state & FDE_ERROR) {
pfd.events |= POLLERR;
}
#if defined(__linux__)
@@ -147,7 +150,6 @@
}
auto post_poll = std::chrono::steady_clock::now();
- std::vector<fdevent_event> poll_events;
for (const auto& pollfd : pollfds) {
unsigned events = 0;
@@ -170,7 +172,7 @@
auto it = this->installed_fdevents_.find(pollfd.fd);
CHECK(it != this->installed_fdevents_.end());
- fdevent* fde = it->second;
+ fdevent* fde = &it->second;
if (events == 0) {
if (fde->timeout) {
@@ -187,7 +189,8 @@
fde->last_active = post_poll;
}
}
- this->HandleEvents(std::move(poll_events));
+ this->HandleEvents(poll_events);
+ poll_events.clear();
}
main_thread_id_.reset();
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 4efbc02..3e781b8 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -276,6 +276,7 @@
class Process {
public:
constexpr explicit Process(HANDLE h = nullptr) : h_(h) {}
+ constexpr Process(Process&& other) : h_(std::exchange(other.h_, nullptr)) {}
~Process() { close(); }
constexpr explicit operator bool() const { return h_ != nullptr; }
@@ -292,6 +293,8 @@
}
private:
+ DISALLOW_COPY_AND_ASSIGN(Process);
+
void close() {
if (*this) {
::CloseHandle(h_);
@@ -666,6 +669,8 @@
class Process {
public:
constexpr explicit Process(pid_t pid) : pid_(pid) {}
+ constexpr Process(Process&& other) : pid_(std::exchange(other.pid_, -1)) {}
+
constexpr explicit operator bool() const { return pid_ >= 0; }
void wait() {
@@ -682,6 +687,8 @@
}
private:
+ DISALLOW_COPY_AND_ASSIGN(Process);
+
pid_t pid_;
};
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index 46d4bd3..2c0989e 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -34,14 +34,54 @@
#include <stdlib.h>
#include <string.h>
-void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline) {
+static void bootimg_set_cmdline_v3(boot_img_hdr_v3* h, const std::string& cmdline) {
if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
}
+void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline) {
+ if (h->header_version == 3) {
+ return bootimg_set_cmdline_v3(reinterpret_cast<boot_img_hdr_v3*>(h), cmdline);
+ }
+ if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
+ strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
+}
+
+static boot_img_hdr_v3* mkbootimg_v3(const std::vector<char>& kernel,
+ const std::vector<char>& ramdisk, const boot_img_hdr_v2& src,
+ std::vector<char>* out) {
+#define V3_PAGE_SIZE 4096
+ const size_t page_mask = V3_PAGE_SIZE - 1;
+ int64_t kernel_actual = (kernel.size() + page_mask) & (~page_mask);
+ int64_t ramdisk_actual = (ramdisk.size() + page_mask) & (~page_mask);
+
+ int64_t bootimg_size = V3_PAGE_SIZE + kernel_actual + ramdisk_actual;
+ out->resize(bootimg_size);
+
+ boot_img_hdr_v3* hdr = reinterpret_cast<boot_img_hdr_v3*>(out->data());
+
+ memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
+ hdr->kernel_size = kernel.size();
+ hdr->ramdisk_size = ramdisk.size();
+ hdr->os_version = src.os_version;
+ hdr->header_size = sizeof(boot_img_hdr_v3);
+ hdr->header_version = 3;
+
+ memcpy(hdr->magic + V3_PAGE_SIZE, kernel.data(), kernel.size());
+ memcpy(hdr->magic + V3_PAGE_SIZE + kernel_actual, ramdisk.data(), ramdisk.size());
+
+ return hdr;
+}
+
boot_img_hdr_v2* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
const std::vector<char>& second, const std::vector<char>& dtb,
size_t base, const boot_img_hdr_v2& src, std::vector<char>* out) {
+ if (src.header_version == 3) {
+ if (!second.empty() || !dtb.empty()) {
+ die("Second stage bootloader and dtb not supported in v3 boot image\n");
+ }
+ return reinterpret_cast<boot_img_hdr_v2*>(mkbootimg_v3(kernel, ramdisk, src, out));
+ }
const size_t page_mask = src.page_size - 1;
int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 7fdc28b..7f6e723 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -464,7 +464,7 @@
}
// Is this actually a boot image?
- if (kernel_data.size() < sizeof(boot_img_hdr_v2)) {
+ if (kernel_data.size() < sizeof(boot_img_hdr_v3)) {
die("cannot load '%s': too short", kernel.c_str());
}
if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
@@ -493,7 +493,7 @@
std::vector<char> dtb_data;
if (!g_dtb_path.empty()) {
- if (g_boot_img_hdr.header_version < 2) {
+ if (g_boot_img_hdr.header_version != 2) {
die("Argument dtb not supported for boot image header version %d\n",
g_boot_img_hdr.header_version);
}
diff --git a/init/init.cpp b/init/init.cpp
index b29dfa3..4289dcf 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -713,8 +713,15 @@
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
- // Will handle EPIPE at the time of write by checking the errno
- signal(SIGPIPE, SIG_IGN);
+ // Init should not crash because of a dependence on any other process, therefore we ignore
+ // SIGPIPE and handle EPIPE at the call site directly. Note that setting a signal to SIG_IGN
+ // is inherited across exec, but custom signal handlers are not. Since we do not want to
+ // ignore SIGPIPE for child processes, we set a no-op function for the signal handler instead.
+ {
+ struct sigaction action = {.sa_flags = SA_RESTART};
+ action.sa_handler = [](int) {};
+ sigaction(SIGPIPE, &action, nullptr);
+ }
// Set init and its forked children's oom_adj.
if (auto result =
diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h
index ad9b04e..0b0df2b 100644
--- a/libstats/pull/include/stats_pull_atom_callback.h
+++ b/libstats/pull/include/stats_pull_atom_callback.h
@@ -112,6 +112,8 @@
* invoke the callback when the stats service determines that this atom needs to be
* pulled.
*
+ * Requires the REGISTER_STATS_PULL_ATOM permission.
+ *
* \param atom_tag The tag of the atom for this pull atom callback.
* \param metadata Optional metadata specifying the timeout, cool down time, and
* additive fields for mapping isolated to host uids.
@@ -128,6 +130,8 @@
* Unregisters a callback for an atom when that atom is to be pulled. Note that any ongoing
* pulls will still occur.
*
+ * Requires the REGISTER_STATS_PULL_ATOM permission.
+ *
* \param atomTag The tag of the atom of which to unregister
*/
void AStatsManager_unregisterPullAtomCallback(int32_t atom_tag);
diff --git a/storaged/main.cpp b/storaged/main.cpp
index a7bda14..bbed210 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -71,6 +71,7 @@
bool flag_dump_perf = false;
int opt;
+ signal(SIGPIPE, SIG_IGN);
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
for (;;) {