Merge "Accept DexMetadata files (.dm) for install-multiple"
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 1f59d64..dfcc52d 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -94,7 +94,7 @@
WriteFdExactly(fd.get(), "restarting in USB mode\n");
}
-bool reboot_service_impl(unique_fd fd, const std::string& arg) {
+void reboot_service(unique_fd fd, const std::string& arg) {
std::string reboot_arg = arg;
bool auto_reboot = false;
@@ -108,7 +108,7 @@
if (reboot_arg == "sideload") {
if (getuid() != 0) {
WriteFdExactly(fd.get(), "'adb root' is required for 'adb reboot sideload'.\n");
- return false;
+ return;
}
const std::vector<std::string> options = {auto_reboot ? "--sideload_auto_reboot"
@@ -116,7 +116,7 @@
std::string err;
if (!write_bootloader_message(options, &err)) {
D("Failed to set bootloader message: %s", err.c_str());
- return false;
+ return;
}
reboot_arg = "recovery";
@@ -128,16 +128,9 @@
std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str());
- return false;
- }
-
- return true;
-}
-
-void reboot_service(unique_fd fd, const std::string& arg) {
- if (!reboot_service_impl(std::move(fd), arg)) {
return;
}
+
// Don't return early. Give the reboot command time to take effect
// to avoid messing up scripts which do "adb reboot && adb wait-for-device"
while (true) {
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 9222008..3c74c75 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1190,17 +1190,11 @@
}
#endif // ADB_HOST
-int register_socket_transport(unique_fd s, const char* serial, int port, int local,
+int register_socket_transport(unique_fd s, std::string serial, int port, int local,
atransport::ReconnectCallback reconnect) {
atransport* t = new atransport(std::move(reconnect), kCsOffline);
- if (!serial) {
- char buf[32];
- snprintf(buf, sizeof(buf), "T-%p", t);
- serial = buf;
- }
-
- D("transport: %s init'ing for socket %d, on port %d", serial, s.get(), port);
+ D("transport: %s init'ing for socket %d, on port %d", serial.c_str(), s.get(), port);
if (init_socket_transport(t, std::move(s), port, local) < 0) {
delete t;
return -1;
@@ -1208,7 +1202,7 @@
std::unique_lock<std::recursive_mutex> lock(transport_lock);
for (const auto& transport : pending_list) {
- if (strcmp(serial, transport->serial.c_str()) == 0) {
+ if (serial == transport->serial) {
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in pending_list and fails to register";
delete t;
@@ -1217,7 +1211,7 @@
}
for (const auto& transport : transport_list) {
- if (strcmp(serial, transport->serial.c_str()) == 0) {
+ if (serial == transport->serial) {
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in transport_list and fails to register";
delete t;
@@ -1225,8 +1219,8 @@
}
}
+ t->serial = std::move(serial);
pending_list.push_front(t);
- t->serial = serial;
lock.unlock();
diff --git a/adb/transport.h b/adb/transport.h
index 1844ae8..4bfc2ce 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -364,7 +364,7 @@
void connect_device(const std::string& address, std::string* response);
/* cause new transports to be init'd and added to the list */
-int register_socket_transport(unique_fd s, const char* serial, int port, int local,
+int register_socket_transport(unique_fd s, std::string serial, int port, int local,
atransport::ReconnectCallback reconnect);
// This should only be used for transports with connection_state == kCsNoPerm.
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 9398ceb..3b1552e 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -125,8 +125,7 @@
return init_socket_transport(t, std::move(fd), port, 0) >= 0;
};
- int ret =
- register_socket_transport(std::move(fd), serial.c_str(), port, 0, std::move(reconnect));
+ int ret = register_socket_transport(std::move(fd), serial, port, 0, std::move(reconnect));
if (ret < 0) {
if (ret == -EALREADY) {
*response = android::base::StringPrintf("already connected to %s", serial.c_str());
@@ -162,7 +161,7 @@
close_on_exec(fd.get());
disable_tcp_nagle(fd.get());
std::string serial = getEmulatorSerialString(console_port);
- if (register_socket_transport(std::move(fd), serial.c_str(), adb_port, 1,
+ if (register_socket_transport(std::move(fd), std::move(serial), adb_port, 1,
[](atransport*) { return false; }) == 0) {
return 0;
}
@@ -265,7 +264,7 @@
close_on_exec(fd.get());
disable_tcp_nagle(fd.get());
std::string serial = android::base::StringPrintf("host-%d", fd.get());
- register_socket_transport(std::move(fd), serial.c_str(), port, 1,
+ register_socket_transport(std::move(fd), std::move(serial), port, 1,
[](atransport*) { return false; });
}
}
@@ -362,7 +361,7 @@
* exchange. */
std::string serial = android::base::StringPrintf("host-%d", fd.get());
WriteFdExactly(fd.get(), _start_req, strlen(_start_req));
- register_socket_transport(std::move(fd), serial.c_str(), port, 1,
+ register_socket_transport(std::move(fd), std::move(serial), port, 1,
[](atransport*) { return false; });
}
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index aabc620..55ca65d 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -134,7 +134,7 @@
return ret;
}
- std::regex reg("partition-size[[:s:]]*:[[:s:]]*([[:w:]]+)[[:s:]]*:[[:s:]]*0x([[:d:]]+)");
+ std::regex reg("partition-size[[:s:]]*:[[:s:]]*([[:w:]]+)[[:s:]]*:[[:s:]]*0x([[:xdigit:]]+)");
std::smatch sm;
for (auto& s : all) {
@@ -264,11 +264,16 @@
std::vector<std::string>* info) {
RetCode ret;
int dsize;
- if ((ret = RawCommand(Commands::UPLOAD, response, info, &dsize)) || dsize == 0) {
- error_ = "Upload request failed";
+ if ((ret = RawCommand(Commands::UPLOAD, response, info, &dsize))) {
+ error_ = "Upload request failed: " + error_;
return ret;
}
+ if (!dsize) {
+ error_ = "Upload request failed, device reports 0 bytes available";
+ return BAD_DEV_RESP;
+ }
+
std::vector<char> data;
data.resize(dsize);
@@ -462,10 +467,10 @@
}
RetCode FastBootDriver::SendBuffer(const void* buf, size_t size) {
+ // ioctl on 0-length buffer causes freezing
if (!size) {
- return SUCCESS;
+ return BAD_ARG;
}
-
// Write the buffer
ssize_t tmp = transport->Write(buf, size);
@@ -521,7 +526,7 @@
// Now we need to send a multiple of chunk size
size_t nchunks = (len - total) / TRANSPORT_CHUNK_SIZE;
size_t nbytes = TRANSPORT_CHUNK_SIZE * nchunks;
- if (SendBuffer(data + total, nbytes)) {
+ if (nbytes && SendBuffer(data + total, nbytes)) { // Don't send a ZLP
error_ = ErrnoStr("Send failed in SparseWriteCallback()");
return -1;
}
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 9fdd317..e8711cb 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -103,7 +103,7 @@
/* HELPERS */
void SetInfoCallback(std::function<void(std::string&)> info);
- const std::string RCString(RetCode rc);
+ static const std::string RCString(RetCode rc);
std::string Error();
RetCode WaitForDisconnect();
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index 05e03e1..aa68ceb 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -133,7 +133,11 @@
bool DestroyLogicalPartition(const std::string& name) {
DeviceMapper& dm = DeviceMapper::Instance();
- return dm.DeleteDevice(name);
+ if (!dm.DeleteDevice(name)) {
+ return false;
+ }
+ LINFO << "Unmapped logical partition " << name;
+ return true;
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index d6eee6b..2015e4d 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -48,10 +48,20 @@
PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
return false;
}
- if (ioctl(fd, BLKALIGNOFF, &device_info->alignment_offset) < 0) {
+
+ int alignment_offset;
+ if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
return false;
}
+ int logical_block_size;
+ if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
+ return false;
+ }
+
+ device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
+ device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
return true;
#else
(void)block_device;
@@ -74,6 +84,19 @@
void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
size_ += extent->num_sectors() * LP_SECTOR_SIZE;
+
+ if (LinearExtent* new_extent = extent->AsLinearExtent()) {
+ if (!extents_.empty() && extents_.back()->AsLinearExtent() &&
+ extents_.back()->AsLinearExtent()->end_sector() == new_extent->physical_sector()) {
+ // If the previous extent can be merged into this new one, do so
+ // to avoid creating unnecessary extents.
+ LinearExtent* prev_extent = extents_.back()->AsLinearExtent();
+ extent = std::make_unique<LinearExtent>(
+ prev_extent->num_sectors() + new_extent->num_sectors(),
+ prev_extent->physical_sector());
+ extents_.pop_back();
+ }
+ }
extents_.push_back(std::move(extent));
}
@@ -178,6 +201,7 @@
device_info_.alignment = geometry_.alignment;
device_info_.alignment_offset = geometry_.alignment_offset;
+ device_info_.logical_block_size = geometry_.logical_block_size;
return true;
}
@@ -201,6 +225,10 @@
LERROR << "Block device size must be a multiple of 512.";
return false;
}
+ if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) {
+ LERROR << "Logical block size must be a multiple of 512.";
+ return false;
+ }
if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) {
LERROR << "Alignment offset is not sector-aligned.";
return false;
@@ -244,6 +272,18 @@
return false;
}
+ // Finally, the size of the allocatable space must be a multiple of the
+ // logical block size. If we have no more free space after this
+ // computation, then we abort. Note that the last sector is inclusive,
+ // so we have to account for that.
+ uint64_t num_free_sectors = last_sector - first_sector + 1;
+ uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
+ if (num_free_sectors < sectors_per_block) {
+ LERROR << "Not enough space to allocate any partition tables.";
+ return false;
+ }
+ last_sector = first_sector + (num_free_sectors / sectors_per_block) * sectors_per_block - 1;
+
geometry_.first_logical_sector = first_sector;
geometry_.last_logical_sector = last_sector;
geometry_.metadata_max_size = metadata_max_size;
@@ -251,6 +291,7 @@
geometry_.alignment = device_info_.alignment;
geometry_.alignment_offset = device_info_.alignment_offset;
geometry_.block_device_size = device_info_.size;
+ geometry_.logical_block_size = device_info.logical_block_size;
return true;
}
@@ -297,87 +338,93 @@
uint64_t end;
Interval(uint64_t start, uint64_t end) : start(start), end(end) {}
+ uint64_t length() const { return end - start; }
bool operator<(const Interval& other) const { return start < other.start; }
};
- std::vector<Interval> intervals;
- // Collect all extents in the partition table.
+ // Collect all extents in the partition table, then sort them by starting
+ // sector.
+ std::vector<Interval> extents;
for (const auto& partition : partitions_) {
for (const auto& extent : partition->extents()) {
LinearExtent* linear = extent->AsLinearExtent();
if (!linear) {
continue;
}
- intervals.emplace_back(linear->physical_sector(),
- linear->physical_sector() + extent->num_sectors());
+ extents.emplace_back(linear->physical_sector(),
+ linear->physical_sector() + extent->num_sectors());
}
}
+ std::sort(extents.begin(), extents.end());
- // Sort extents by starting sector.
- std::sort(intervals.begin(), intervals.end());
+ // Convert the extent list into a list of gaps between the extents; i.e.,
+ // the list of ranges that are free on the disk.
+ std::vector<Interval> free_regions;
+ for (size_t i = 1; i < extents.size(); i++) {
+ const Interval& previous = extents[i - 1];
+ const Interval& current = extents[i];
+
+ uint64_t aligned = AlignSector(previous.end);
+ if (aligned >= current.start) {
+ // There is no gap between these two extents, try the next one.
+ // Note that we check with >= instead of >, since alignment may
+ // bump the ending sector past the beginning of the next extent.
+ continue;
+ }
+
+ // The new interval represents the free space starting at the end of
+ // the previous interval, and ending at the start of the next interval.
+ free_regions.emplace_back(aligned, current.start);
+ }
+
+ // Add a final interval representing the remainder of the free space.
+ uint64_t last_free_extent_start =
+ extents.empty() ? geometry_.first_logical_sector : extents.back().end;
+ last_free_extent_start = AlignSector(last_free_extent_start);
+ if (last_free_extent_start <= geometry_.last_logical_sector) {
+ free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1);
+ }
+
+ const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
+ CHECK(sectors_needed % sectors_per_block == 0);
// Find gaps that we can use for new extents. Note we store new extents in a
// temporary vector, and only commit them if we are guaranteed enough free
// space.
std::vector<std::unique_ptr<LinearExtent>> new_extents;
- for (size_t i = 1; i < intervals.size(); i++) {
- const Interval& previous = intervals[i - 1];
- const Interval& current = intervals[i];
+ for (auto& region : free_regions) {
+ if (region.length() % sectors_per_block != 0) {
+ // This should never happen, because it would imply that we
+ // once allocated an extent that was not a multiple of the
+ // block size. That extent would be rejected by DM_TABLE_LOAD.
+ LERROR << "Region " << region.start << ".." << region.end
+ << " is not a multiple of the block size, " << sectors_per_block;
- if (previous.end >= current.start) {
- // There is no gap between these two extents, try the next one. Note that
- // extents may never overlap, but just for safety, we ignore them if they
- // do.
- DCHECK(previous.end == current.start);
- continue;
+ // If for some reason the final region is mis-sized we still want
+ // to be able to grow partitions. So just to be safe, round the
+ // region down to the nearest block.
+ region.end = region.start + (region.length() / sectors_per_block) * sectors_per_block;
+ if (!region.length()) {
+ continue;
+ }
}
- uint64_t aligned = AlignSector(previous.end);
- if (aligned >= current.start) {
- // After alignment, this extent is not usable.
- continue;
- }
+ uint64_t sectors = std::min(sectors_needed, region.length());
+ CHECK(sectors % sectors_per_block == 0);
- // This gap is enough to hold the remainder of the space requested, so we
- // can allocate what we need and return.
- if (current.start - aligned >= sectors_needed) {
- auto extent = std::make_unique<LinearExtent>(sectors_needed, aligned);
- sectors_needed -= extent->num_sectors();
- new_extents.push_back(std::move(extent));
+ auto extent = std::make_unique<LinearExtent>(sectors, region.start);
+ new_extents.push_back(std::move(extent));
+ sectors_needed -= sectors;
+ if (!sectors_needed) {
break;
}
-
- // This gap is not big enough to fit the remainder of the space requested,
- // so consume the whole thing and keep looking for more.
- auto extent = std::make_unique<LinearExtent>(current.start - aligned, aligned);
- sectors_needed -= extent->num_sectors();
- new_extents.push_back(std::move(extent));
}
-
- // If we still have more to allocate, take it from the remaining free space
- // in the allocatable region.
if (sectors_needed) {
- uint64_t first_sector;
- if (intervals.empty()) {
- first_sector = geometry_.first_logical_sector;
- } else {
- first_sector = intervals.back().end;
- }
- DCHECK(first_sector <= geometry_.last_logical_sector);
-
- // Note: After alignment, |first_sector| may be > the last usable sector.
- first_sector = AlignSector(first_sector);
-
- // Note: the last usable sector is inclusive.
- if (first_sector > geometry_.last_logical_sector ||
- geometry_.last_logical_sector + 1 - first_sector < sectors_needed) {
- LERROR << "Not enough free space to expand partition: " << partition->name();
- return false;
- }
- auto extent = std::make_unique<LinearExtent>(sectors_needed, first_sector);
- new_extents.push_back(std::move(extent));
+ LERROR << "Not enough free space to expand partition: " << partition->name();
+ return false;
}
+ // Everything succeeded, so commit the new extents.
for (auto& extent : new_extents) {
partition->AddExtent(std::move(extent));
}
@@ -445,6 +492,12 @@
void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) {
device_info_.size = device_info.size;
+ // Note that if the logical block size changes, we're probably in trouble:
+ // we could have already built extents that will only work on the previous
+ // size.
+ DCHECK(partitions_.empty() ||
+ device_info_.logical_block_size == device_info.logical_block_size);
+
// The kernel does not guarantee these values are present, so we only
// replace existing values if the new values are non-zero.
if (device_info.alignment) {
@@ -457,14 +510,19 @@
bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
// Align the space needed up to the nearest sector.
- uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE);
+ uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size);
+ uint64_t old_size = partition->size();
- if (aligned_size > partition->size()) {
- return GrowPartition(partition, aligned_size);
- }
- if (aligned_size < partition->size()) {
+ if (aligned_size > old_size) {
+ if (!GrowPartition(partition, aligned_size)) {
+ return false;
+ }
+ } else if (aligned_size < partition->size()) {
ShrinkPartition(partition, aligned_size);
}
+
+ LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to "
+ << aligned_size << " bytes";
return true;
}
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 4334d51..da9c8f3 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -69,6 +69,11 @@
EXPECT_EQ(system->size(), 131072);
EXPECT_EQ(system->extents().size(), 1);
EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE);
+ // Test resizing again, that the extents are merged together.
+ builder->ResizePartition(system, 1024 * 256);
+ EXPECT_EQ(system->size(), 1024 * 256);
+ EXPECT_EQ(system->extents().size(), 1);
+ EXPECT_EQ(system->extents()[0]->num_sectors(), (1024 * 256) / LP_SECTOR_SIZE);
// Test shrinking within the same extent.
builder->ResizePartition(system, 32768);
@@ -92,11 +97,11 @@
Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 10000), true);
- EXPECT_EQ(system->size(), 10240);
+ EXPECT_EQ(system->size(), 12288);
EXPECT_EQ(system->extents().size(), 1);
- builder->ResizePartition(system, 9000);
- EXPECT_EQ(system->size(), 9216);
+ builder->ResizePartition(system, 7000);
+ EXPECT_EQ(system->size(), 8192);
EXPECT_EQ(system->extents().size(), 1);
}
@@ -120,13 +125,13 @@
TEST(liblp, InternalAlignment) {
// Test the metadata fitting within alignment.
- BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0);
+ BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 1536);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2035);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
// Test a large alignment offset thrown in.
device_info.alignment_offset = 753664;
@@ -135,7 +140,7 @@
exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 1472);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2035);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
// Alignment offset without alignment doesn't mean anything.
device_info.alignment = 0;
@@ -150,7 +155,7 @@
exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 78);
- EXPECT_EQ(exported->geometry.last_logical_sector, 1975);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 1973);
// Test a small alignment with no alignment offset.
device_info.alignment = 11 * 1024;
@@ -163,7 +168,7 @@
}
TEST(liblp, InternalPartitionAlignment) {
- BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664);
+ BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
Partition* a = builder->AddPartition("a", TEST_GUID, 0);
@@ -381,7 +386,7 @@
static const size_t kMetadataSize = 64 * 1024;
// No space to store metadata + geometry.
- BlockDeviceInfo device_info(kDiskSize, 0, 0);
+ BlockDeviceInfo device_info(kDiskSize, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
@@ -390,8 +395,8 @@
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
- // Space for metadata + geometry + one free sector.
- device_info.size += LP_SECTOR_SIZE;
+ // Space for metadata + geometry + one free block.
+ device_info.size += device_info.logical_block_size;
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_NE(builder, nullptr);
@@ -424,19 +429,21 @@
ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
ASSERT_LE(device_info.alignment_offset, INT_MAX);
+ ASSERT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
// Having an alignment offset > alignment doesn't really make sense.
ASSERT_LT(device_info.alignment_offset, device_info.alignment);
}
TEST(liblp, UpdateBlockDeviceInfo) {
- BlockDeviceInfo device_info(1024 * 1024, 4096, 1024);
+ BlockDeviceInfo device_info(1024 * 1024, 4096, 1024, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
EXPECT_EQ(builder->block_device_info().size, device_info.size);
EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment);
EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset);
+ EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size);
device_info.alignment = 0;
device_info.alignment_offset = 2048;
@@ -450,3 +457,27 @@
EXPECT_EQ(builder->block_device_info().alignment, 8192);
EXPECT_EQ(builder->block_device_info().alignment_offset, 2048);
}
+
+TEST(liblp, InvalidBlockSize) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 513);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ EXPECT_EQ(builder, nullptr);
+}
+
+TEST(liblp, AlignedExtentSize) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* partition = builder->AddPartition("system", TEST_GUID, 0);
+ ASSERT_NE(partition, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(partition, 512));
+ EXPECT_EQ(partition->size(), 4096);
+}
+
+TEST(liblp, AlignedFreeSpace) {
+ // Only one sector free - at least one block is required.
+ BlockDeviceInfo device_info(10240, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
+ ASSERT_EQ(builder, nullptr);
+}
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 0f96e3a..a35cf8e 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -32,11 +32,16 @@
// By default, partitions are aligned on a 1MiB boundary.
static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
+static const uint32_t kDefaultBlockSize = 4096;
struct BlockDeviceInfo {
- BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0) {}
- BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset)
- : size(size), alignment(alignment), alignment_offset(alignment_offset) {}
+ BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
+ BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
+ uint32_t logical_block_size)
+ : size(size),
+ alignment(alignment),
+ alignment_offset(alignment_offset),
+ logical_block_size(logical_block_size) {}
// Size of the block device, in bytes.
uint64_t size;
// Optimal target alignment, in bytes. Partition extents will be aligned to
@@ -46,6 +51,8 @@
// |alignment_offset| on the target device is correctly aligned on its
// parent device. This value must be 0 or a multiple of 512.
uint32_t alignment_offset;
+ // Block size, for aligning extent sizes and partition sizes.
+ uint32_t logical_block_size;
};
// Abstraction around dm-targets that can be encoded into logical partition tables.
@@ -74,6 +81,7 @@
LinearExtent* AsLinearExtent() override { return this; }
uint64_t physical_sector() const { return physical_sector_; }
+ uint64_t end_sector() const { return physical_sector_ + num_sectors_; }
private:
uint64_t physical_sector_;
@@ -88,6 +96,8 @@
};
class Partition final {
+ friend class MetadataBuilder;
+
public:
Partition(const std::string& name, const std::string& guid, uint32_t attributes);
@@ -97,10 +107,6 @@
// Remove all extents from this partition.
void RemoveExtents();
- // Remove and/or shrink extents until the partition is the requested size.
- // See MetadataBuilder::ShrinkPartition for more information.
- void ShrinkTo(uint64_t requested_size);
-
const std::string& name() const { return name_; }
uint32_t attributes() const { return attributes_; }
const std::string& guid() const { return guid_; }
@@ -108,6 +114,8 @@
uint64_t size() const { return size_; }
private:
+ void ShrinkTo(uint64_t aligned_size);
+
std::string name_;
std::string guid_;
std::vector<std::unique_ptr<Extent>> extents_;
@@ -144,7 +152,7 @@
// size. This is a convenience method for tests.
static std::unique_ptr<MetadataBuilder> New(uint64_t blockdev_size, uint32_t metadata_max_size,
uint32_t metadata_slot_count) {
- BlockDeviceInfo device_info(blockdev_size, 0, 0);
+ BlockDeviceInfo device_info(blockdev_size, 0, 0, kDefaultBlockSize);
return New(device_info, metadata_max_size, metadata_slot_count);
}
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index e1323e1..52c80f7 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -136,6 +136,12 @@
* can be used to verify the geometry against a target device.
*/
uint64_t block_device_size;
+
+ /* 76: Logical block size of the super partition block device. This is the
+ * minimal alignment for partition and extent sizes, and it must be a
+ * multiple of LP_SECTOR_SIZE.
+ */
+ uint32_t logical_block_size;
} __attribute__((packed)) LpMetadataGeometry;
/* The logical partition metadata has a number of tables; they are described
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 4522275..6ef5124 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -26,6 +26,8 @@
#include "liblp/metadata_format.h"
#define LP_TAG "[liblp]"
+#define LWARN LOG(WARNING) << LP_TAG
+#define LINFO LOG(INFO) << LP_TAG
#define LERROR LOG(ERROR) << LP_TAG
#define PERROR PLOG(ERROR) << LP_TAG
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 092dbf1..7bf42ae 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -40,7 +40,8 @@
80000,
0,
0,
- 1024 * 1024};
+ 1024 * 1024,
+ 4096};
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 4096);
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 4096 + 16384);
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 4096 + 16384 * 2);
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 156319b..fc9d83f 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -304,7 +304,11 @@
PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
return false;
}
- return FlashPartitionTable(fd, metadata, slot_number);
+ if (!FlashPartitionTable(fd, metadata, slot_number)) {
+ return false;
+ }
+ LWARN << "Flashed new logical partition geometry to " << block_device;
+ return true;
}
bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
@@ -314,7 +318,12 @@
PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
return false;
}
- return UpdatePartitionTable(fd, metadata, slot_number);
+ if (!UpdatePartitionTable(fd, metadata, slot_number)) {
+ return false;
+ }
+ LINFO << "Updated logical partition table at slot " << slot_number << " on device "
+ << block_device;
+ return true;
}
bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
diff --git a/init/Android.bp b/init/Android.bp
index 660d586..a93bb66 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -127,7 +127,6 @@
"ueventd.cpp",
"ueventd_parser.cpp",
"util.cpp",
- "watchdogd.cpp",
],
whole_static_libs: ["libcap"],
header_libs: ["bootimg_headers"],
@@ -157,7 +156,6 @@
srcs: ["main.cpp"],
symlinks: [
"sbin/ueventd",
- "sbin/watchdogd",
],
}
*/
diff --git a/init/Android.mk b/init/Android.mk
index d0cb820..9d9d368 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -98,7 +98,6 @@
# Create symlinks.
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
- ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_EXECUTABLE)
diff --git a/init/devices.cpp b/init/devices.cpp
index ed4a739..58c8b2e 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -34,7 +34,7 @@
#include "util.h"
#ifdef _INIT_INIT_H
-#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
+#error "Do not include init.h in files used by ueventd; it will expose init's globals"
#endif
using android::base::Basename;
@@ -372,7 +372,7 @@
}
}
-void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {
+void DeviceHandler::HandleUevent(const Uevent& uevent) {
if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
FixupSysPermissions(uevent.path, uevent.subsystem);
}
@@ -418,6 +418,10 @@
HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
}
+void DeviceHandler::ColdbootDone() {
+ skip_restorecon_ = true;
+}
+
DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
std::vector<SysfsPermissions> sysfs_permissions,
std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
diff --git a/init/devices.h b/init/devices.h
index 0be660f..9d39eaa 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -29,6 +29,7 @@
#include <selinux/label.h>
#include "uevent.h"
+#include "uevent_handler.h"
namespace android {
namespace init {
@@ -105,7 +106,7 @@
std::string dir_name_ = "/dev";
};
-class DeviceHandler {
+class DeviceHandler : public UeventHandler {
public:
friend class DeviceHandlerTester;
@@ -113,11 +114,12 @@
DeviceHandler(std::vector<Permissions> dev_permissions,
std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> subsystems,
std::set<std::string> boot_devices, bool skip_restorecon);
+ virtual ~DeviceHandler() = default;
- void HandleDeviceEvent(const Uevent& uevent);
+ void HandleUevent(const Uevent& uevent) override;
+ void ColdbootDone() override;
std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
- void set_skip_restorecon(bool value) { skip_restorecon_ = value; }
private:
bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 28bda34..740e82c 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -35,8 +35,6 @@
namespace android {
namespace init {
-std::vector<std::string> firmware_directories;
-
static void LoadFirmware(const Uevent& uevent, const std::string& root, int fw_fd, size_t fw_size,
int loading_fd, int data_fd) {
// Start transfer.
@@ -58,7 +56,10 @@
return access("/dev/.booting", F_OK) == 0;
}
-static void ProcessFirmwareEvent(const Uevent& uevent) {
+FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories)
+ : firmware_directories_(std::move(firmware_directories)) {}
+
+void FirmwareHandler::ProcessFirmwareEvent(const Uevent& uevent) {
int booting = IsBooting();
LOG(INFO) << "firmware: loading '" << uevent.firmware << "' for '" << uevent.path << "'";
@@ -80,7 +81,7 @@
}
try_loading_again:
- for (const auto& firmware_directory : firmware_directories) {
+ for (const auto& firmware_directory : firmware_directories_) {
std::string file = firmware_directory + uevent.firmware;
unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
struct stat sb;
@@ -104,7 +105,7 @@
write(loading_fd, "-1", 2);
}
-void HandleFirmwareEvent(const Uevent& uevent) {
+void FirmwareHandler::HandleUevent(const Uevent& uevent) {
if (uevent.subsystem != "firmware" || uevent.action != "add") return;
// Loading the firmware in a child means we can do that in parallel...
diff --git a/init/firmware_handler.h b/init/firmware_handler.h
index 6081511..3996096 100644
--- a/init/firmware_handler.h
+++ b/init/firmware_handler.h
@@ -21,13 +21,23 @@
#include <vector>
#include "uevent.h"
+#include "uevent_handler.h"
namespace android {
namespace init {
-extern std::vector<std::string> firmware_directories;
+class FirmwareHandler : public UeventHandler {
+ public:
+ explicit FirmwareHandler(std::vector<std::string> firmware_directories);
+ virtual ~FirmwareHandler() = default;
-void HandleFirmwareEvent(const Uevent& uevent);
+ void HandleUevent(const Uevent& uevent) override;
+
+ private:
+ void ProcessFirmwareEvent(const Uevent& uevent);
+
+ std::vector<std::string> firmware_directories_;
+};
} // namespace init
} // namespace android
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 43075b2..41e8fff 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -206,7 +206,7 @@
bool found = false;
auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
if (uevent.path == dm_path) {
- device_handler_->HandleDeviceEvent(uevent);
+ device_handler_->HandleUevent(uevent);
found = true;
return ListenerAction::kStop;
}
@@ -273,7 +273,7 @@
lp_metadata_partition_ = links[0];
}
required_devices_partition_names_.erase(iter);
- device_handler_->HandleDeviceEvent(uevent);
+ device_handler_->HandleUevent(uevent);
if (required_devices_partition_names_.empty()) {
return ListenerAction::kStop;
} else {
@@ -310,7 +310,7 @@
auto verity_callback = [&device_name, &dm_device, this, &found](const Uevent& uevent) {
if (uevent.device_name == device_name) {
LOG(VERBOSE) << "Creating device-mapper device : " << dm_device;
- device_handler_->HandleDeviceEvent(uevent);
+ device_handler_->HandleUevent(uevent);
found = true;
return ListenerAction::kStop;
}
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index 2352fc7..8866bdc 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -41,10 +41,9 @@
}
// selinux.h
-bool SelinuxHasVendorInit() {
- return true;
+int SelinuxGetVendorAndroidVersion() {
+ return 10000;
}
-
void SelabelInitialize() {}
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index f0e1f07..0af11f6 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -23,6 +23,9 @@
#include <string>
+// android/api-level.h
+#define __ANDROID_API_P__ 28
+
// sys/system_properties.h
#define PROP_VALUE_MAX 92
@@ -41,7 +44,7 @@
const std::string& source_context, const ucred& cr, std::string* error);
// selinux.h
-bool SelinuxHasVendorInit();
+int SelinuxGetVendorAndroidVersion();
void SelabelInitialize();
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
diff --git a/init/init.cpp b/init/init.cpp
index 7ad9ec3..e0cce0e 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -58,7 +58,6 @@
#include "sigchld_handler.h"
#include "ueventd.h"
#include "util.h"
-#include "watchdogd.h"
using namespace std::chrono_literals;
using namespace std::string_literals;
@@ -617,10 +616,6 @@
return ueventd_main(argc, argv);
}
- if (!strcmp(basename(argv[0]), "watchdogd")) {
- return watchdogd_main(argc, argv);
- }
-
if (argc > 1 && !strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap function_map;
diff --git a/init/init.h b/init/init.h
index 6c82fa1..f244ad7 100644
--- a/init/init.h
+++ b/init/init.h
@@ -31,8 +31,8 @@
namespace android {
namespace init {
-// Note: These globals are *only* valid in init, so they should not be used in ueventd,
-// watchdogd, or any files that may be included in those, such as devices.cpp and util.cpp.
+// Note: These globals are *only* valid in init, so they should not be used in ueventd
+// or any files that may be included in ueventd, such as devices.cpp and util.cpp.
// TODO: Have an Init class and remove all globals.
extern std::string default_console;
extern std::vector<std::string> late_import_paths;
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp
index 1734a7e..1e0db57 100644
--- a/init/modalias_handler.cpp
+++ b/init/modalias_handler.cpp
@@ -139,7 +139,7 @@
return Insmod(dependencies[0], args);
}
-void ModaliasHandler::HandleModaliasEvent(const Uevent& uevent) {
+void ModaliasHandler::HandleUevent(const Uevent& uevent) {
if (uevent.modalias.empty()) return;
for (const auto& [alias, module] : module_aliases_) {
diff --git a/init/modalias_handler.h b/init/modalias_handler.h
index e79da32..3247c86 100644
--- a/init/modalias_handler.h
+++ b/init/modalias_handler.h
@@ -16,22 +16,23 @@
#pragma once
-#include "result.h"
-#include "uevent.h"
-
#include <string>
#include <unordered_map>
#include <vector>
+#include "result.h"
+#include "uevent.h"
+#include "uevent_handler.h"
+
namespace android {
namespace init {
-class ModaliasHandler {
+class ModaliasHandler : public UeventHandler {
public:
ModaliasHandler();
- ~ModaliasHandler(){};
+ virtual ~ModaliasHandler() = default;
- void HandleModaliasEvent(const Uevent& uevent);
+ void HandleUevent(const Uevent& uevent) override;
private:
Result<Success> InsmodWithDeps(const std::string& module_name, const std::string& args);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index c0d811f..cd2f630 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -16,6 +16,7 @@
#include "property_service.h"
+#include <android/api-level.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -576,7 +577,7 @@
size_t flen = 0;
const char* context = kInitContext.c_str();
- if (SelinuxHasVendorInit()) {
+ if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
if (StartsWith(filename, path_prefix)) {
context = secontext;
diff --git a/init/selinux.cpp b/init/selinux.cpp
index b788be9..fd7e86f 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -47,6 +47,7 @@
#include "selinux.h"
+#include <android/api-level.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
@@ -472,29 +473,27 @@
selinux_set_callback(SELINUX_CB_LOG, cb);
}
-// This function checks whether the sepolicy supports vendor init.
-bool SelinuxHasVendorInit() {
+// This function returns the Android version with which the vendor SEPolicy was compiled.
+// It is used for version checks such as whether or not vendor_init should be used
+int SelinuxGetVendorAndroidVersion() {
if (!IsSplitPolicyDevice()) {
- // If this device does not split sepolicy files, vendor_init will be available in the latest
- // monolithic sepolicy file.
- return true;
+ // If this device does not split sepolicy files, it's not a Treble device and therefore,
+ // we assume it's always on the latest platform.
+ return __ANDROID_API_FUTURE__;
}
std::string version;
if (!GetVendorMappingVersion(&version)) {
- // Return true as the default if we failed to load the vendor sepolicy version.
- return true;
+ LOG(FATAL) << "Could not read vendor SELinux version";
}
int major_version;
std::string major_version_str(version, 0, version.find('.'));
if (!ParseInt(major_version_str, &major_version)) {
- PLOG(ERROR) << "Failed to parse the vendor sepolicy major version " << major_version_str;
- // Return true as the default if we failed to parse the major version.
- return true;
+ PLOG(FATAL) << "Failed to parse the vendor sepolicy major version " << major_version_str;
}
- return major_version >= 28;
+ return major_version;
}
// selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
diff --git a/init/selinux.h b/init/selinux.h
index 30069b5..c41d7f0 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -27,7 +27,7 @@
void SelinuxRestoreContext();
void SelinuxSetupKernelLogging();
-bool SelinuxHasVendorInit();
+int SelinuxGetVendorAndroidVersion();
void SelabelInitialize();
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
diff --git a/init/service.cpp b/init/service.cpp
index 4c2747e..d20e90a 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -46,10 +46,12 @@
#include "util.h"
#if defined(__ANDROID__)
+#include <android/api-level.h>
#include <sys/system_properties.h>
#include "init.h"
#include "property_service.h"
+#include "selinux.h"
#else
#include "host_init_stubs.h"
#endif
@@ -1211,6 +1213,13 @@
}
std::vector<std::string> str_args(args.begin() + 2, args.end());
+
+ if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
+ if (str_args[0] == "/sbin/watchdogd") {
+ str_args[0] = "/system/bin/watchdogd";
+ }
+ }
+
service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
return Success();
}
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index ee72513..c2a21d4 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -30,6 +30,7 @@
#include "util.h"
#if defined(__ANDROID__)
+#include <android/api-level.h>
#include "property_service.h"
#include "selinux.h"
#else
@@ -355,7 +356,7 @@
static bool shutting_down;
std::vector<Subcontext>* InitializeSubcontexts() {
- if (SelinuxHasVendorInit()) {
+ if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
subcontexts.emplace_back(path_prefix, secontext);
}
diff --git a/init/watchdogd.h b/init/uevent_handler.h
similarity index 71%
rename from init/watchdogd.h
rename to init/uevent_handler.h
index 73f77d5..75d1990 100644
--- a/init/watchdogd.h
+++ b/init/uevent_handler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,21 @@
* limitations under the License.
*/
-#ifndef _INIT_WATCHDOGD_H_
-#define _INIT_WATCHDOGD_H_
+#pragma once
+
+#include "uevent.h"
namespace android {
namespace init {
-int watchdogd_main(int argc, char **argv);
+class UeventHandler {
+ public:
+ virtual ~UeventHandler() = default;
+
+ virtual void HandleUevent(const Uevent& uevent) = 0;
+
+ virtual void ColdbootDone() {}
+};
} // namespace init
} // namespace android
-
-#endif
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index e9d829b..95be6af 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -38,6 +38,7 @@
#include "firmware_handler.h"
#include "modalias_handler.h"
#include "selinux.h"
+#include "uevent_handler.h"
#include "uevent_listener.h"
#include "ueventd_parser.h"
#include "util.h"
@@ -107,11 +108,10 @@
class ColdBoot {
public:
- ColdBoot(UeventListener& uevent_listener, DeviceHandler& device_handler,
- ModaliasHandler& modalias_handler)
+ ColdBoot(UeventListener& uevent_listener,
+ std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers)
: uevent_listener_(uevent_listener),
- device_handler_(device_handler),
- modalias_handler_(modalias_handler),
+ uevent_handlers_(uevent_handlers),
num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {}
void Run();
@@ -124,8 +124,7 @@
void WaitForSubProcesses();
UeventListener& uevent_listener_;
- DeviceHandler& device_handler_;
- ModaliasHandler& modalias_handler_;
+ std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers_;
unsigned int num_handler_subprocesses_;
std::vector<Uevent> uevent_queue_;
@@ -136,16 +135,16 @@
void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) {
for (unsigned int i = process_num; i < uevent_queue_.size(); i += total_processes) {
auto& uevent = uevent_queue_[i];
- device_handler_.HandleDeviceEvent(uevent);
- modalias_handler_.HandleModaliasEvent(uevent);
+
+ for (auto& uevent_handler : uevent_handlers_) {
+ uevent_handler->HandleUevent(uevent);
+ }
}
_exit(EXIT_SUCCESS);
}
void ColdBoot::RegenerateUevents() {
uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
- HandleFirmwareEvent(uevent);
-
uevent_queue_.emplace_back(std::move(uevent));
return ListenerAction::kContinue;
});
@@ -168,7 +167,6 @@
void ColdBoot::DoRestoreCon() {
selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
- device_handler_.set_skip_restorecon(false);
}
void ColdBoot::WaitForSubProcesses() {
@@ -234,8 +232,7 @@
SelinuxSetupKernelLogging();
SelabelInitialize();
- DeviceHandler device_handler;
- ModaliasHandler modalias_handler;
+ std::vector<std::unique_ptr<UeventHandler>> uevent_handlers;
UeventListener uevent_listener;
{
@@ -248,19 +245,27 @@
ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", "/odm/ueventd.rc",
"/ueventd." + hardware + ".rc"});
- device_handler = DeviceHandler{std::move(ueventd_configuration.dev_permissions),
- std::move(ueventd_configuration.sysfs_permissions),
- std::move(ueventd_configuration.subsystems),
- fs_mgr_get_boot_devices(), true};
+ uevent_handlers.emplace_back(std::make_unique<DeviceHandler>(
+ std::move(ueventd_configuration.dev_permissions),
+ std::move(ueventd_configuration.sysfs_permissions),
+ std::move(ueventd_configuration.subsystems), fs_mgr_get_boot_devices(), true));
+ uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>(
+ std::move(ueventd_configuration.firmware_directories)));
- firmware_directories = ueventd_configuration.firmware_directories;
+ if (ueventd_configuration.enable_modalias_handling) {
+ uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>());
+ }
}
if (access(COLDBOOT_DONE, F_OK) != 0) {
- ColdBoot cold_boot(uevent_listener, device_handler, modalias_handler);
+ ColdBoot cold_boot(uevent_listener, uevent_handlers);
cold_boot.Run();
}
+ for (auto& uevent_handler : uevent_handlers) {
+ uevent_handler->ColdbootDone();
+ }
+
// We use waitpid() in ColdBoot, so we can't ignore SIGCHLD until now.
signal(SIGCHLD, SIG_IGN);
// Reap and pending children that exited between the last call to waitpid() and setting SIG_IGN
@@ -268,10 +273,10 @@
while (waitpid(-1, nullptr, WNOHANG) > 0) {
}
- uevent_listener.Poll([&device_handler, &modalias_handler](const Uevent& uevent) {
- HandleFirmwareEvent(uevent);
- modalias_handler.HandleModaliasEvent(uevent);
- device_handler.HandleDeviceEvent(uevent);
+ uevent_listener.Poll([&uevent_handlers](const Uevent& uevent) {
+ for (auto& uevent_handler : uevent_handlers) {
+ uevent_handler->HandleUevent(uevent);
+ }
return ListenerAction::kContinue;
});
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 54b0d16..677938e 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -84,6 +84,23 @@
return Success();
}
+Result<Success> ParseModaliasHandlingLine(std::vector<std::string>&& args,
+ bool* enable_modalias_handling) {
+ if (args.size() != 2) {
+ return Error() << "modalias_handling lines take exactly one parameter";
+ }
+
+ if (args[1] == "enabled") {
+ *enable_modalias_handling = true;
+ } else if (args[1] == "disabled") {
+ *enable_modalias_handling = false;
+ } else {
+ return Error() << "modalias_handling takes either 'enabled' or 'disabled' as a parameter";
+ }
+
+ return Success();
+}
+
class SubsystemParser : public SectionParser {
public:
SubsystemParser(std::vector<Subsystem>* subsystems) : subsystems_(subsystems) {}
@@ -182,6 +199,9 @@
parser.AddSingleLineParser("firmware_directories",
std::bind(ParseFirmwareDirectoriesLine, _1,
&ueventd_configuration.firmware_directories));
+ parser.AddSingleLineParser("modalias_handling",
+ std::bind(ParseModaliasHandlingLine, _1,
+ &ueventd_configuration.enable_modalias_handling));
for (const auto& config : configs) {
parser.ParseConfig(config);
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index 343d58b..7d30edf 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -30,6 +30,7 @@
std::vector<SysfsPermissions> sysfs_permissions;
std::vector<Permissions> dev_permissions;
std::vector<std::string> firmware_directories;
+ bool enable_modalias_handling = false;
};
UeventdConfiguration ParseConfig(const std::vector<std::string>& configs);
diff --git a/init/util.cpp b/init/util.cpp
index 7735717..105ac87 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -47,7 +47,7 @@
#endif
#ifdef _INIT_INIT_H
-#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
+#error "Do not include init.h in files used by ueventd; it will expose init's globals"
#endif
using android::base::boot_clock;
diff --git a/libpixelflinger/fixed.cpp b/libpixelflinger/fixed.cpp
index 5094537..de6b479 100644
--- a/libpixelflinger/fixed.cpp
+++ b/libpixelflinger/fixed.cpp
@@ -70,17 +70,6 @@
// ------------------------------------------------------------------------
-GGLfixed gglFastDivx(GGLfixed n, GGLfixed d)
-{
- if ((d>>24) && ((d>>24)+1)) {
- n >>= 8;
- d >>= 8;
- }
- return gglMulx(n, gglRecip(d));
-}
-
-// ------------------------------------------------------------------------
-
static const GGLfixed ggl_sqrt_reciproc_approx_tab[8] = {
// 1/sqrt(x) with x = 1-N/16, N=[8...1]
0x16A09, 0x15555, 0x143D1, 0x134BF, 0x1279A, 0x11C01, 0x111AC, 0x10865
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
index 51e9e26..7f39e9b 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
@@ -86,7 +86,6 @@
GGLfixed gglPowx(GGLfixed x, GGLfixed y) CONST;
GGLfixed gglSqrtx(GGLfixed a) CONST;
GGLfixed gglSqrtRecipx(GGLfixed x) CONST;
-GGLfixed gglFastDivx(GGLfixed n, GGLfixed d) CONST;
int32_t gglMulDivi(int32_t a, int32_t b, int32_t c);
int32_t gglRecipQNormalized(int32_t x, int* exponent);
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index df5da65..be2145d 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -190,6 +190,7 @@
"tests/MemoryRangeTest.cpp",
"tests/MemoryRemoteTest.cpp",
"tests/MemoryTest.cpp",
+ "tests/RegsInfoTest.cpp",
"tests/RegsIterateTest.cpp",
"tests/RegsStepIfSignalHandlerTest.cpp",
"tests/RegsTest.cpp",
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index 47825f5..e6dd33c 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -25,11 +25,13 @@
template <typename AddressType>
struct RegsInfo {
+ static constexpr size_t MAX_REGISTERS = 64;
+
RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
RegsImpl<AddressType>* regs = nullptr;
uint64_t saved_reg_map = 0;
- AddressType saved_regs[64];
+ AddressType saved_regs[MAX_REGISTERS];
inline AddressType Get(uint32_t reg) {
if (IsSaved(reg)) {
@@ -39,23 +41,23 @@
}
inline AddressType* Save(uint32_t reg) {
- if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
- // This should never happen as since all currently supported
- // architectures have the total number of registers < 64.
+ if (reg > MAX_REGISTERS) {
+ // This should never happen since all currently supported
+ // architectures have < 64 total registers.
abort();
}
- saved_reg_map |= 1 << reg;
+ saved_reg_map |= 1ULL << reg;
saved_regs[reg] = (*regs)[reg];
return &(*regs)[reg];
}
inline bool IsSaved(uint32_t reg) {
- if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
- // This should never happen as since all currently supported
- // architectures have the total number of registers < 64.
+ if (reg > MAX_REGISTERS) {
+ // This should never happen since all currently supported
+ // architectures have < 64 total registers.
abort();
}
- return saved_reg_map & (1 << reg);
+ return saved_reg_map & (1ULL << reg);
}
inline uint16_t Total() { return regs->total_regs(); }
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
new file mode 100644
index 0000000..052b5bf
--- /dev/null
+++ b/libunwindstack/tests/RegsInfoTest.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Regs.h>
+
+#include "RegsFake.h"
+#include "RegsInfo.h"
+
+namespace unwindstack {
+
+TEST(RegsInfoTest, single_uint32_t) {
+ RegsImplFake<uint32_t> regs(10);
+ RegsInfo<uint32_t> info(®s);
+
+ regs[1] = 0x100;
+ ASSERT_FALSE(info.IsSaved(1));
+ ASSERT_EQ(0x100U, info.Get(1));
+ ASSERT_EQ(10, info.Total());
+
+ uint32_t* value = info.Save(1);
+ ASSERT_EQ(value, ®s[1]);
+ regs[1] = 0x200;
+ ASSERT_TRUE(info.IsSaved(1));
+ ASSERT_EQ(0x100U, info.Get(1));
+ ASSERT_EQ(0x200U, regs[1]);
+}
+
+TEST(RegsInfoTest, single_uint64_t) {
+ RegsImplFake<uint64_t> regs(20);
+ RegsInfo<uint64_t> info(®s);
+
+ regs[3] = 0x300;
+ ASSERT_FALSE(info.IsSaved(3));
+ ASSERT_EQ(0x300U, info.Get(3));
+ ASSERT_EQ(20, info.Total());
+
+ uint64_t* value = info.Save(3);
+ ASSERT_EQ(value, ®s[3]);
+ regs[3] = 0x400;
+ ASSERT_TRUE(info.IsSaved(3));
+ ASSERT_EQ(0x300U, info.Get(3));
+ ASSERT_EQ(0x400U, regs[3]);
+}
+
+TEST(RegsInfoTest, all) {
+ RegsImplFake<uint64_t> regs(64);
+ RegsInfo<uint64_t> info(®s);
+
+ for (uint32_t i = 0; i < 64; i++) {
+ regs[i] = i * 0x100;
+ ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+ }
+
+ for (uint32_t i = 0; i < 64; i++) {
+ ASSERT_FALSE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+ uint64_t* reg = info.Save(i);
+ ASSERT_EQ(reg, ®s[i]) << "Reg " + std::to_string(i) + " failed.";
+ *reg = i * 0x1000 + 0x100;
+ ASSERT_EQ(i * 0x1000 + 0x100, regs[i]) << "Reg " + std::to_string(i) + " failed.";
+ }
+
+ for (uint32_t i = 0; i < 64; i++) {
+ ASSERT_TRUE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+ ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+ }
+}
+
+} // namespace unwindstack
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index 2efda86..9ac082f 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -7,17 +7,8 @@
"liblog",
],
local_include_dirs: ["include"],
- cflags: ["-Werror"],
-
+ cflags: ["-Werror", "-DLMKD_TRACE_KILLS"],
init_rc: ["lmkd.rc"],
-
- product_variables: {
- debuggable: {
- cflags: [
- "-DLMKD_TRACE_KILLS"
- ],
- },
- },
}
cc_library_static {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index c2487d6..1a14be3 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -52,8 +52,8 @@
#else /* LMKD_TRACE_KILLS */
-#define TRACE_KILL_START(pid)
-#define TRACE_KILL_END()
+#define TRACE_KILL_START(pid) ((void)(pid))
+#define TRACE_KILL_END() ((void)0)
#endif /* LMKD_TRACE_KILLS */
@@ -111,6 +111,7 @@
static bool kill_heaviest_task;
static unsigned long kill_timeout_ms;
static bool use_minfree_levels;
+static bool per_app_memcg;
/* data required to handle events */
struct event_handler_info {
@@ -472,7 +473,7 @@
return;
}
- if (low_ram_device) {
+ if (per_app_memcg) {
if (params.oomadj >= 900) {
soft_limit_mult = 0;
} else if (params.oomadj >= 800) {
@@ -1481,6 +1482,8 @@
(unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
use_minfree_levels =
property_get_bool("ro.lmk.use_minfree_levels", false);
+ per_app_memcg =
+ property_get_bool("ro.config.per_app_memcg", low_ram_device);
if (!init()) {
if (!use_inkernel_interface) {
diff --git a/watchdogd/Android.bp b/watchdogd/Android.bp
new file mode 100644
index 0000000..0fbc33c
--- /dev/null
+++ b/watchdogd/Android.bp
@@ -0,0 +1,14 @@
+cc_binary {
+ name: "watchdogd",
+ recovery_available: true,
+ srcs: ["watchdogd.cpp"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ shared_libs: ["libbase"],
+ sanitize: {
+ misc_undefined: ["signed-integer-overflow"],
+ },
+}
diff --git a/init/watchdogd.cpp b/watchdogd/watchdogd.cpp
similarity index 79%
rename from init/watchdogd.cpp
rename to watchdogd/watchdogd.cpp
index e03a2c3..5dc41e6 100644
--- a/init/watchdogd.cpp
+++ b/watchdogd/watchdogd.cpp
@@ -23,16 +23,9 @@
#include <android-base/logging.h>
-#ifdef _INIT_INIT_H
-#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
-#endif
-
#define DEV_NAME "/dev/watchdog"
-namespace android {
-namespace init {
-
-int watchdogd_main(int argc, char **argv) {
+int main(int argc, char** argv) {
android::base::InitLogging(argv, &android::base::KernelLogger);
int interval = 10;
@@ -43,7 +36,7 @@
LOG(INFO) << "watchdogd started (interval " << interval << ", margin " << margin << ")!";
- int fd = open(DEV_NAME, O_RDWR|O_CLOEXEC);
+ int fd = open(DEV_NAME, O_RDWR | O_CLOEXEC);
if (fd == -1) {
PLOG(ERROR) << "Failed to open " << DEV_NAME;
return 1;
@@ -63,9 +56,8 @@
interval = 1;
}
LOG(WARNING) << "Adjusted interval to timeout returned by driver: "
- << "timeout " << timeout
- << ", interval " << interval
- << ", margin " << margin;
+ << "timeout " << timeout << ", interval " << interval << ", margin "
+ << margin;
}
}
@@ -74,6 +66,3 @@
sleep(interval);
}
}
-
-} // namespace init
-} // namespace android