Merge "Internalize subclasses of Memory"
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 1abae87..ac739c4 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -169,12 +169,12 @@
};
struct UsbFfsConnection : public Connection {
- UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write,
+ UsbFfsConnection(unique_fd* control, unique_fd read, unique_fd write,
std::promise<void> destruction_notifier)
: worker_started_(false),
stopped_(false),
destruction_notifier_(std::move(destruction_notifier)),
- control_fd_(std::move(control)),
+ control_fd_(control),
read_fd_(std::move(read)),
write_fd_(std::move(write)) {
LOG(INFO) << "UsbFfsConnection constructed";
@@ -183,11 +183,6 @@
PLOG(FATAL) << "failed to create eventfd";
}
- monitor_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
- if (monitor_event_fd_ == -1) {
- PLOG(FATAL) << "failed to create eventfd";
- }
-
aio_context_ = ScopedAioContext::Create(kUsbReadQueueDepth + kUsbWriteQueueDepth);
}
@@ -199,7 +194,6 @@
// We need to explicitly close our file descriptors before we notify our destruction,
// because the thread listening on the future will immediately try to reopen the endpoint.
aio_context_.reset();
- control_fd_.reset();
read_fd_.reset();
write_fd_.reset();
@@ -246,13 +240,6 @@
PLOG(FATAL) << "failed to notify worker eventfd to stop UsbFfsConnection";
}
CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
-
- rc = adb_write(monitor_event_fd_.get(), ¬ify, sizeof(notify));
- if (rc < 0) {
- PLOG(FATAL) << "failed to notify monitor eventfd to stop UsbFfsConnection";
- }
-
- CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
}
private:
@@ -271,33 +258,24 @@
monitor_thread_ = std::thread([this]() {
adb_thread_setname("UsbFfs-monitor");
- bool bound = false;
bool enabled = false;
bool running = true;
while (running) {
adb_pollfd pfd[2] = {
- { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
- { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
+ {.fd = control_fd_->get(), .events = POLLIN, .revents = 0},
};
- // If we don't see our first bind within a second, try again.
- int timeout_ms = bound ? -1 : 1000;
-
- int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout_ms));
+ int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1));
if (rc == -1) {
PLOG(FATAL) << "poll on USB control fd failed";
- } else if (rc == 0) {
- LOG(WARNING) << "timed out while waiting for FUNCTIONFS_BIND, trying again";
- break;
}
if (pfd[1].revents) {
- // We were told to die.
- break;
+ // We were told to die, continue reading until FUNCTIONFS_UNBIND.
}
struct usb_functionfs_event event;
- rc = TEMP_FAILURE_RETRY(adb_read(control_fd_.get(), &event, sizeof(event)));
+ rc = TEMP_FAILURE_RETRY(adb_read(control_fd_->get(), &event, sizeof(event)));
if (rc == -1) {
PLOG(FATAL) << "failed to read functionfs event";
} else if (rc == 0) {
@@ -313,28 +291,10 @@
switch (event.type) {
case FUNCTIONFS_BIND:
- if (bound) {
- LOG(WARNING) << "received FUNCTIONFS_BIND while already bound?";
- running = false;
- break;
- }
-
- if (enabled) {
- LOG(WARNING) << "received FUNCTIONFS_BIND while already enabled?";
- running = false;
- break;
- }
-
- bound = true;
+ LOG(FATAL) << "received FUNCTIONFS_BIND after already opened?";
break;
case FUNCTIONFS_ENABLE:
- if (!bound) {
- LOG(WARNING) << "received FUNCTIONFS_ENABLE while not bound?";
- running = false;
- break;
- }
-
if (enabled) {
LOG(WARNING) << "received FUNCTIONFS_ENABLE while already enabled?";
running = false;
@@ -346,10 +306,6 @@
break;
case FUNCTIONFS_DISABLE:
- if (!bound) {
- LOG(WARNING) << "received FUNCTIONFS_DISABLE while not bound?";
- }
-
if (!enabled) {
LOG(WARNING) << "received FUNCTIONFS_DISABLE while not enabled?";
}
@@ -363,11 +319,6 @@
LOG(WARNING) << "received FUNCTIONFS_UNBIND while still enabled?";
}
- if (!bound) {
- LOG(WARNING) << "received FUNCTIONFS_UNBIND when not bound?";
- }
-
- bound = false;
running = false;
break;
@@ -381,7 +332,7 @@
if ((event.u.setup.bRequestType & USB_DIR_IN)) {
LOG(INFO) << "acking device-to-host control transfer";
- ssize_t rc = adb_write(control_fd_.get(), "", 0);
+ ssize_t rc = adb_write(control_fd_->get(), "", 0);
if (rc != 0) {
PLOG(ERROR) << "failed to write empty packet to host";
break;
@@ -390,7 +341,7 @@
std::string buf;
buf.resize(event.u.setup.wLength + 1);
- ssize_t rc = adb_read(control_fd_.get(), buf.data(), buf.size());
+ ssize_t rc = adb_read(control_fd_->get(), buf.data(), buf.size());
if (rc != event.u.setup.wLength) {
LOG(ERROR)
<< "read " << rc
@@ -426,6 +377,12 @@
uint64_t dummy;
ssize_t rc = adb_read(worker_event_fd_.get(), &dummy, sizeof(dummy));
if (rc == -1) {
+ if (errno == EINTR) {
+ // We were interrupted either to stop, or because of a backtrace.
+ // Check stopped_ again to see if we need to exit.
+ continue;
+ }
+
PLOG(FATAL) << "failed to read from eventfd";
} else if (rc == 0) {
LOG(FATAL) << "hit EOF on eventfd";
@@ -462,6 +419,7 @@
}
worker_thread_.join();
+ worker_started_ = false;
}
void PrepareReadBlock(IoBlock* block, uint64_t id) {
@@ -679,10 +637,13 @@
std::once_flag error_flag_;
unique_fd worker_event_fd_;
- unique_fd monitor_event_fd_;
ScopedAioContext aio_context_;
- unique_fd control_fd_;
+
+ // We keep a pointer to the control fd, so that we can reuse it to avoid USB reconfiguration,
+ // and still be able to reset it to force a reopen after FUNCTIONFS_UNBIND or running into an
+ // unexpected situation.
+ unique_fd* control_fd_;
unique_fd read_fd_;
unique_fd write_fd_;
@@ -711,15 +672,16 @@
static void usb_ffs_open_thread() {
adb_thread_setname("usb ffs open");
+ unique_fd control;
+ unique_fd bulk_out;
+ unique_fd bulk_in;
+
while (true) {
if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) {
LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy";
return usb_init_legacy();
}
- unique_fd control;
- unique_fd bulk_out;
- unique_fd bulk_in;
if (!open_functionfs(&control, &bulk_out, &bulk_in)) {
std::this_thread::sleep_for(1s);
continue;
@@ -730,7 +692,7 @@
std::promise<void> destruction_notifier;
std::future<void> future = destruction_notifier.get_future();
transport->SetConnection(std::make_unique<UsbFfsConnection>(
- std::move(control), std::move(bulk_out), std::move(bulk_in),
+ &control, std::move(bulk_out), std::move(bulk_in),
std::move(destruction_notifier)));
register_transport(transport);
future.wait();
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index a64ce40..1b54022 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -297,8 +297,32 @@
PLOG(ERROR) << "failed to write USB strings";
return false;
}
- // Signal only when writing the descriptors to ffs
+
+ // Signal init after we've wwritten our descriptors.
android::base::SetProperty("sys.usb.ffs.ready", "1");
+
+ // Read until we get FUNCTIONFS_BIND from the control endpoint.
+ while (true) {
+ struct usb_functionfs_event event;
+ ssize_t rc = TEMP_FAILURE_RETRY(adb_read(control.get(), &event, sizeof(event)));
+
+ if (rc == -1) {
+ PLOG(FATAL) << "failed to read from FFS control fd";
+ } else if (rc == 0) {
+ LOG(WARNING) << "hit EOF on functionfs control fd during initialization";
+ } else if (rc != sizeof(event)) {
+ LOG(FATAL) << "read functionfs event of unexpected size, expected " << sizeof(event)
+ << ", got " << rc;
+ }
+
+ if (event.type != FUNCTIONFS_BIND) {
+ LOG(FATAL) << "first read on functionfs control fd returned non-bind: "
+ << event.type;
+ } else {
+ break;
+ }
+ }
+
*out_control = std::move(control);
}
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
index 897c48f..4a8e1ef 100644
--- a/base/include/android-base/result.h
+++ b/base/include/android-base/result.h
@@ -81,8 +81,7 @@
struct ResultError {
template <typename T>
- ResultError(T&& message, int code)
- : message_(std::forward<T>(message)), code_(code) {}
+ ResultError(T&& message, int code) : message_(std::forward<T>(message)), code_(code) {}
template <typename T>
operator android::base::expected<T, ResultError>() {
@@ -122,18 +121,16 @@
template <typename T>
Error& operator<<(T&& t) {
+ if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError>) {
+ errno_ = t.code();
+ return (*this) << t.message();
+ }
int saved = errno;
ss_ << t;
errno = saved;
return *this;
}
- Error& operator<<(const ResultError& result_error) {
- (*this) << result_error.message();
- errno_ = result_error.code();
- return *this;
- }
-
const std::string str() const {
std::string str = ss_.str();
if (append_errno_) {
diff --git a/base/result_test.cpp b/base/result_test.cpp
index 72f97f4..e864b97 100644
--- a/base/result_test.cpp
+++ b/base/result_test.cpp
@@ -143,8 +143,8 @@
ASSERT_FALSE(result2);
ASSERT_FALSE(result2.has_value());
- EXPECT_EQ(0, result.error().code());
- EXPECT_EQ(error_text, result.error().message());
+ EXPECT_EQ(0, result2.error().code());
+ EXPECT_EQ(error_text, result2.error().message());
}
TEST(result, result_error_through_ostream) {
@@ -159,8 +159,8 @@
ASSERT_FALSE(result2);
ASSERT_FALSE(result2.has_value());
- EXPECT_EQ(0, result.error().code());
- EXPECT_EQ(error_text, result.error().message());
+ EXPECT_EQ(0, result2.error().code());
+ EXPECT_EQ(error_text, result2.error().message());
}
TEST(result, result_errno_error_through_ostream) {
@@ -179,8 +179,8 @@
ASSERT_FALSE(result2);
ASSERT_FALSE(result2.has_value());
- EXPECT_EQ(test_errno, result.error().code());
- EXPECT_EQ(error_text + ": " + strerror(test_errno), result.error().message());
+ EXPECT_EQ(test_errno, result2.error().code());
+ EXPECT_EQ(error_text + ": " + strerror(test_errno), result2.error().message());
}
TEST(result, constructor_forwarding) {
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 1b09f79..2e9c2d6 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -94,7 +94,7 @@
{FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
{FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
{FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
- {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
+ {FB_VAR_PARTITION_SIZE, {::GetPartitionSize, GetAllPartitionArgsWithSlot}},
{FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
{FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
{FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 46bfe92..45c3ede 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -106,6 +106,13 @@
EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
EXPECT_EQ(extent->physical_sector(), 32);
+ auto exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_EQ(FindPartition(*exported.get(), "not found"), nullptr);
+ auto entry = FindPartition(*exported.get(), "system");
+ ASSERT_NE(entry, nullptr);
+ ASSERT_EQ(GetPartitionSize(*exported.get(), *entry), 32768);
+
// Test shrinking to 0.
builder->ResizePartition(system, 0);
EXPECT_EQ(system->size(), 0);
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index d3a7b93..135a1b3 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -107,6 +107,10 @@
std::string SlotSuffixForSlotNumber(uint32_t slot_number);
std::string GetPartitionSlotSuffix(const std::string& partition_name);
+// Helpers for common functions.
+const LpMetadataPartition* FindPartition(const LpMetadata& metadata, const std::string& name);
+uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition);
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 72a3c57..338b525 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -135,6 +135,24 @@
return list;
}
+const LpMetadataPartition* FindPartition(const LpMetadata& metadata, const std::string& name) {
+ for (const auto& partition : metadata.partitions) {
+ if (GetPartitionName(partition) == name) {
+ return &partition;
+ }
+ }
+ return nullptr;
+}
+
+uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition) {
+ uint64_t total_size = 0;
+ for (uint32_t i = 0; i < partition.num_extents; i++) {
+ const auto& extent = metadata.extents[partition.first_extent_index + i];
+ total_size += extent.num_sectors * LP_SECTOR_SIZE;
+ }
+ return total_size;
+}
+
std::string GetPartitionSlotSuffix(const std::string& partition_name) {
if (partition_name.size() <= 2) {
return "";
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 40d8d90..edc316a 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -150,6 +150,7 @@
}
void SetCgroupAction::EnableResourceCaching() {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
if (fd_ != FDS_NOT_CACHED) {
return;
}
@@ -191,6 +192,7 @@
}
bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
if (IsFdValid()) {
// fd is cached, reuse it
if (!AddTidToCgroup(pid, fd_)) {
@@ -221,6 +223,7 @@
}
bool SetCgroupAction::ExecuteForTask(int tid) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
if (IsFdValid()) {
// fd is cached, reuse it
if (!AddTidToCgroup(tid, fd_)) {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 445647d..77bac2d 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -19,6 +19,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <map>
+#include <mutex>
#include <string>
#include <vector>
@@ -127,6 +128,7 @@
CgroupController controller_;
std::string path_;
android::base::unique_fd fd_;
+ mutable std::mutex fd_mutex_;
static bool IsAppDependentPath(const std::string& path);
static bool AddTidToCgroup(int tid, int fd);
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 3b3f61e..7f129f8 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -187,6 +187,7 @@
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += libcgrouprc.so
namespace.media.link.default.shared_libs += libmediametrics.so
namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%