Merge "Adjust to MapInfo to new api."
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index a0bc44d..0efe384 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -43,6 +43,7 @@
},
},
ramdisk_available: true,
+ vendor_ramdisk_available: true,
}
filegroup {
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 910911e..34049d4 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -174,6 +174,7 @@
"libz",
],
ramdisk_available: true,
+ vendor_ramdisk_available: true,
}
cc_defaults {
@@ -408,9 +409,9 @@
"fs_mgr_defaults",
],
srcs: [
- "snapuserd_server.cpp",
- "snapuserd.cpp",
- "snapuserd_daemon.cpp",
+ "snapuserd_server.cpp",
+ "snapuserd.cpp",
+ "snapuserd_daemon.cpp",
],
cflags: [
@@ -421,7 +422,7 @@
static_libs: [
"libbase",
"libbrotli",
- "libcutils_sockets",
+ "libcutils_sockets",
"liblog",
"libdm",
"libz",
@@ -436,15 +437,9 @@
"snapuserd.rc",
],
static_executable: true,
-}
-
-cc_binary {
- name: "snapuserd_ramdisk",
- stem: "snapuserd",
- defaults: ["snapuserd_defaults"],
-
- ramdisk: true,
- static_executable: true,
+ system_shared_libs: [],
+ ramdisk_available: true,
+ vendor_ramdisk_available: true,
}
cc_test {
@@ -568,7 +563,7 @@
"libsnapshot_snapuserd",
"libcutils_sockets",
"libz",
- "libdm",
+ "libdm",
],
header_libs: [
"libstorage_literals_headers",
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index acb75d0..38c6bf8 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -118,7 +118,7 @@
Cancelled = 7;
};
-// Next: 5
+// Next: 6
message SnapshotUpdateStatus {
UpdateState state = 1;
@@ -133,6 +133,9 @@
// Sectors allocated for metadata in all the snapshot devices.
uint64 metadata_sectors = 4;
+
+ // Whether compression/dm-user was used for any snapshots.
+ bool compression_enabled = 5;
}
// Next: 4
diff --git a/fs_mgr/libsnapshot/device_info.cpp b/fs_mgr/libsnapshot/device_info.cpp
index 8770255..0e90100 100644
--- a/fs_mgr/libsnapshot/device_info.cpp
+++ b/fs_mgr/libsnapshot/device_info.cpp
@@ -120,9 +120,5 @@
#endif
}
-std::string DeviceInfo::GetSnapuserdFirstStagePidVar() const {
- return kSnapuserdFirstStagePidVar;
-}
-
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/device_info.h b/fs_mgr/libsnapshot/device_info.h
index 1f08860..d8d3d91 100644
--- a/fs_mgr/libsnapshot/device_info.h
+++ b/fs_mgr/libsnapshot/device_info.h
@@ -39,7 +39,6 @@
bool SetBootControlMergeStatus(MergeStatus status) override;
bool SetSlotAsUnbootable(unsigned int slot) override;
bool IsRecovery() const override;
- std::string GetSnapuserdFirstStagePidVar() const override;
private:
bool EnsureBootHal();
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
index d5c263d..ef9d648 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
@@ -32,7 +32,6 @@
MOCK_METHOD(bool, SetBootControlMergeStatus, (MergeStatus status), (override));
MOCK_METHOD(bool, SetSlotAsUnbootable, (unsigned int slot), (override));
MOCK_METHOD(bool, IsRecovery, (), (const, override));
- MOCK_METHOD(std::string, GetSnapuserdFirstStagePidVar, (), (const, override));
};
} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 351dce7..f8d3cdc 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -107,7 +107,6 @@
virtual bool SetSlotAsUnbootable(unsigned int slot) = 0;
virtual bool IsRecovery() const = 0;
virtual bool IsTestDevice() const { return false; }
- virtual std::string GetSnapuserdFirstStagePidVar() const = 0;
};
virtual ~ISnapshotManager() = default;
@@ -345,6 +344,18 @@
bool MapAllSnapshots(const std::chrono::milliseconds& timeout_ms = {}) override;
bool UnmapAllSnapshots() override;
+ // We can't use WaitForFile during first-stage init, because ueventd is not
+ // running and therefore will not automatically create symlinks. Instead,
+ // we let init provide us with the correct function to use to ensure
+ // uevents have been processed and symlink/mknod calls completed.
+ void SetUeventRegenCallback(std::function<bool(const std::string&)> callback) {
+ uevent_regen_callback_ = callback;
+ }
+
+ // If true, compression is enabled for this update. This is used by
+ // first-stage to decide whether to launch snapuserd.
+ bool IsSnapuserdRequired();
+
private:
FRIEND_TEST(SnapshotTest, CleanFirstStageMount);
FRIEND_TEST(SnapshotTest, CreateSnapshot);
@@ -676,6 +687,12 @@
// Same as above, but for paths only (no major:minor device strings).
bool GetMappedImageDevicePath(const std::string& device_name, std::string* device_path);
+ // Wait for a device to be created by ueventd (eg, its symlink or node to be populated).
+ // This is needed for any code that uses device-mapper path in first-stage init. If
+ // |timeout_ms| is empty or the given device is not a path, WaitForDevice immediately
+ // returns true.
+ bool WaitForDevice(const std::string& device, std::chrono::milliseconds timeout_ms);
+
std::string gsid_dir_;
std::string metadata_dir_;
std::unique_ptr<IDeviceInfo> device_;
@@ -683,6 +700,7 @@
bool has_local_image_manager_ = false;
bool use_first_stage_snapuserd_ = false;
bool in_factory_data_reset_ = false;
+ std::function<bool(const std::string&)> uevent_regen_callback_;
std::unique_ptr<SnapuserdClient> snapuserd_client_;
};
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
index 0e9ba9e..aa9ba6e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
@@ -30,7 +30,6 @@
static constexpr uint32_t PACKET_SIZE = 512;
-static constexpr char kSnapuserdSocketFirstStage[] = "snapuserd_first_stage";
static constexpr char kSnapuserdSocket[] = "snapuserd";
static constexpr char kSnapuserdFirstStagePidVar[] = "FIRST_STAGE_SNAPUSERD_PID";
@@ -38,10 +37,6 @@
// Ensure that the second-stage daemon for snapuserd is running.
bool EnsureSnapuserdStarted();
-// Start the first-stage version of snapuserd, returning its pid. This is used
-// by first-stage init, as well as vts_libsnapshot_test. On failure, -1 is returned.
-pid_t StartFirstStageSnapuserd();
-
class SnapuserdClient {
private:
android::base::unique_fd sockfd_;
@@ -75,6 +70,11 @@
// Wait for snapuserd to disassociate with a dm-user control device. This
// must ONLY be called if the control device has already been deleted.
bool WaitForDeviceDelete(const std::string& control_device);
+
+ // Detach snapuserd. This shuts down the listener socket, and will cause
+ // snapuserd to gracefully exit once all handler threads have terminated.
+ // This should only be used on first-stage instances of snapuserd.
+ bool DetachSnapuserd();
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
index cadfd71..1491aac 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
@@ -41,6 +41,7 @@
QUERY,
STOP,
DELETE,
+ DETACH,
INVALID,
};
@@ -106,6 +107,7 @@
bool IsTerminating() { return terminating_; }
void RunThread(std::shared_ptr<DmUserHandler> handler);
+ void JoinAllThreads();
// Find a DmUserHandler within a lock.
HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index 1d1510a..7aef086 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -96,7 +96,6 @@
return true;
}
bool IsTestDevice() const override { return true; }
- std::string GetSnapuserdFirstStagePidVar() const override { return {}; }
bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; }
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 10c707a..04c3ccc 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -409,10 +409,12 @@
if (!dm.CreateDevice(name, table, path, timeout_ms)) {
return false;
}
+ if (!WaitForDevice(*path, timeout_ms)) {
+ return false;
+ }
auto control_device = "/dev/dm-user/" + misc_name;
- if (!android::fs_mgr::WaitForFile(control_device, timeout_ms)) {
- LOG(ERROR) << "Timed out waiting for dm-user misc device: " << control_device;
+ if (!WaitForDevice(control_device, timeout_ms)) {
return false;
}
@@ -1340,10 +1342,12 @@
continue;
}
+ auto misc_name = user_cow_name;
+
DmTable table;
- table.Emplace<DmTargetUser>(0, target.spec.length, user_cow_name);
+ table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
if (!dm.LoadTableAndActivate(user_cow_name, table)) {
- LOG(ERROR) << "Unable to swap tables for " << user_cow_name;
+ LOG(ERROR) << "Unable to swap tables for " << misc_name;
continue;
}
@@ -1369,14 +1373,13 @@
}
// Wait for ueventd to acknowledge and create the control device node.
- std::string control_device = "/dev/dm-user/" + user_cow_name;
- if (!android::fs_mgr::WaitForFile(control_device, 10s)) {
- LOG(ERROR) << "Could not find control device: " << control_device;
+ std::string control_device = "/dev/dm-user/" + misc_name;
+ if (!WaitForDevice(control_device, 10s)) {
continue;
}
uint64_t base_sectors =
- snapuserd_client_->InitDmUserCow(user_cow_name, cow_image_device, backing_device);
+ snapuserd_client_->InitDmUserCow(misc_name, cow_image_device, backing_device);
if (base_sectors == 0) {
// Unrecoverable as metadata reads from cow device failed
LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd";
@@ -1385,7 +1388,7 @@
CHECK(base_sectors == target.spec.length);
- if (!snapuserd_client_->AttachDmUser(user_cow_name)) {
+ if (!snapuserd_client_->AttachDmUser(misc_name)) {
// This error is unrecoverable. We cannot proceed because reads to
// the underlying device will fail.
LOG(FATAL) << "Could not initialize snapuserd for " << user_cow_name;
@@ -1399,24 +1402,6 @@
LOG(ERROR) << "Could not transition all snapuserd consumers.";
return false;
}
-
- std::string pid_var = device_->GetSnapuserdFirstStagePidVar();
- if (pid_var.empty()) {
- return true;
- }
-
- int pid;
- const char* pid_str = getenv(pid_var.c_str());
- if (pid_str && android::base::ParseInt(pid_str, &pid)) {
- if (kill(pid, SIGTERM) < 0 && errno != ESRCH) {
- LOG(ERROR) << "kill snapuserd failed";
- return false;
- }
- } else {
- LOG(ERROR) << "Could not find or parse " << kSnapuserdFirstStagePidVar
- << " for snapuserd pid";
- return false;
- }
return true;
}
@@ -1761,15 +1746,6 @@
}
}
- if (use_first_stage_snapuserd_) {
- // Remove the first-stage socket as a precaution, there is no need to
- // access the daemon anymore and we'll be killing it once second-stage
- // is running.
- auto socket = ANDROID_SOCKET_DIR + "/"s + kSnapuserdSocketFirstStage;
- snapuserd_client_ = nullptr;
- unlink(socket.c_str());
- }
-
LOG(INFO) << "Created logical partitions with snapshot.";
return true;
}
@@ -1924,13 +1900,20 @@
if (live_snapshot_status->compression_enabled()) {
auto name = GetDmUserCowName(params.GetPartitionName());
- // :TODO: need to force init to process uevents for these in first-stage.
std::string cow_path;
if (!GetMappedImageDevicePath(cow_name, &cow_path)) {
LOG(ERROR) << "Could not determine path for: " << cow_name;
return false;
}
+ // Ensure both |base_path| and |cow_path| are created, for snapuserd.
+ if (!WaitForDevice(base_path, remaining_time)) {
+ return false;
+ }
+ if (!WaitForDevice(cow_path, remaining_time)) {
+ return false;
+ }
+
std::string new_cow_device;
if (!MapDmUserCow(lock, name, cow_path, base_path, remaining_time, &new_cow_device)) {
LOG(ERROR) << "Could not map dm-user device for partition "
@@ -2070,7 +2053,7 @@
if (!EnsureSnapuserdConnected()) {
return false;
}
- if (!dm.DeleteDevice(dm_user_name)) {
+ if (!dm.DeleteDeviceIfExists(dm_user_name)) {
LOG(ERROR) << "Cannot unmap " << dm_user_name;
return false;
}
@@ -2273,6 +2256,7 @@
bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state) {
SnapshotUpdateStatus status = {};
status.set_state(state);
+ status.set_compression_enabled(IsCompressionEnabled());
return WriteSnapshotUpdateStatus(lock, status);
}
@@ -2408,28 +2392,11 @@
return true;
}
- std::string socket;
- if (use_first_stage_snapuserd_) {
- auto pid = StartFirstStageSnapuserd();
- if (pid < 0) {
- LOG(ERROR) << "Failed to start snapuserd";
- return false;
- }
-
- auto pid_str = std::to_string(static_cast<int>(pid));
- if (setenv(kSnapuserdFirstStagePidVar, pid_str.c_str(), 1) < 0) {
- PLOG(ERROR) << "setenv failed storing the snapuserd pid";
- }
-
- socket = kSnapuserdSocketFirstStage;
- } else {
- if (!EnsureSnapuserdStarted()) {
- return false;
- }
- socket = kSnapuserdSocket;
+ if (!use_first_stage_snapuserd_ && !EnsureSnapuserdStarted()) {
+ return false;
}
- snapuserd_client_ = SnapuserdClient::Connect(socket, 10s);
+ snapuserd_client_ = SnapuserdClient::Connect(kSnapuserdSocket, 10s);
if (!snapuserd_client_) {
LOG(ERROR) << "Unable to connect to snapuserd";
return false;
@@ -2845,7 +2812,7 @@
return nullptr;
}
- if (IsCompressionEnabled()) {
+ if (status.compression_enabled()) {
return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(),
status, paths);
}
@@ -3302,5 +3269,47 @@
return true;
}
+bool SnapshotManager::WaitForDevice(const std::string& device,
+ std::chrono::milliseconds timeout_ms) {
+ if (!android::base::StartsWith(device, "/")) {
+ return true;
+ }
+
+ // In first-stage init, we rely on init setting a callback which can
+ // regenerate uevents and populate /dev for us.
+ if (uevent_regen_callback_) {
+ if (!uevent_regen_callback_(device)) {
+ LOG(ERROR) << "Failed to find device after regenerating uevents: " << device;
+ return false;
+ }
+ return true;
+ }
+
+ // Otherwise, the only kind of device we need to wait for is a dm-user
+ // misc device. Normal calls to DeviceMapper::CreateDevice() guarantee
+ // the path has been created.
+ if (!android::base::StartsWith(device, "/dev/dm-user/")) {
+ return true;
+ }
+
+ if (timeout_ms.count() == 0) {
+ LOG(ERROR) << "No timeout was specified to wait for device: " << device;
+ return false;
+ }
+ if (!android::fs_mgr::WaitForFile(device, timeout_ms)) {
+ LOG(ERROR) << "Timed out waiting for device to appear: " << device;
+ return false;
+ }
+ return true;
+}
+
+bool SnapshotManager::IsSnapuserdRequired() {
+ auto lock = LockExclusive();
+ if (!lock) return false;
+
+ auto status = ReadSnapshotUpdateStatus(lock.get());
+ return status.state() != UpdateState::None && status.compression_enabled();
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
index 092ee0b..5319e69 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
@@ -124,7 +124,6 @@
return data_->allow_set_slot_as_unbootable();
}
bool IsRecovery() const override { return data_->is_recovery(); }
- std::string GetSnapuserdFirstStagePidVar() const override { return {}; }
void SwitchSlot() { switched_slot_ = !switched_slot_; }
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 74558ab..c6a1786 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -1760,9 +1760,6 @@
GTEST_SKIP() << "Skipping Virtual A/B Compression test";
}
- AutoKill auto_kill(StartFirstStageSnapuserd());
- ASSERT_TRUE(auto_kill.valid());
-
// Ensure a connection to the second-stage daemon, but use the first-stage
// code paths thereafter.
ASSERT_TRUE(sm->EnsureSnapuserdConnected());
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 954699c..49e6c3d 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -28,6 +28,9 @@
using namespace android::dm;
using android::base::unique_fd;
+#define SNAP_LOG(level) LOG(level) << misc_name_ << ": "
+#define SNAP_PLOG(level) PLOG(level) << misc_name_ << ": "
+
static constexpr size_t PAYLOAD_SIZE = (1UL << 16);
static_assert(PAYLOAD_SIZE >= BLOCK_SIZE);
@@ -94,7 +97,7 @@
// it will be de-compressed.
bool Snapuserd::ProcessReplaceOp(const CowOperation* cow_op) {
if (!reader_->ReadData(*cow_op, &bufsink_)) {
- LOG(ERROR) << "ReadData failed for chunk: " << cow_op->new_block;
+ SNAP_LOG(ERROR) << "ReadData failed for chunk: " << cow_op->new_block;
return false;
}
@@ -111,7 +114,7 @@
// if the successive blocks are contiguous.
if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SIZE,
cow_op->source * BLOCK_SIZE)) {
- LOG(ERROR) << "Copy-op failed. Read from backing store at: " << cow_op->source;
+ SNAP_LOG(ERROR) << "Copy-op failed. Read from backing store at: " << cow_op->source;
return false;
}
@@ -180,14 +183,14 @@
}
default: {
- LOG(ERROR) << "Unknown operation-type found: " << cow_op->type;
+ SNAP_LOG(ERROR) << "Unknown operation-type found: " << cow_op->type;
ret = false;
break;
}
}
if (!ret) {
- LOG(ERROR) << "ReadData failed for operation: " << cow_op->type;
+ SNAP_LOG(ERROR) << "ReadData failed for operation: " << cow_op->type;
return false;
}
@@ -322,7 +325,7 @@
CHECK(!(*unmerged_exceptions == exceptions_per_area_));
- LOG(DEBUG) << "Unmerged_Exceptions: " << *unmerged_exceptions << " Offset: " << offset;
+ SNAP_LOG(DEBUG) << "Unmerged_Exceptions: " << *unmerged_exceptions << " Offset: " << offset;
return offset;
}
@@ -331,7 +334,7 @@
int merged_ops_cur_iter = 0;
// Find the operations which are merged in this cycle.
- while ((unmerged_exceptions + merged_ops_cur_iter) <= exceptions_per_area_) {
+ while ((unmerged_exceptions + merged_ops_cur_iter) < exceptions_per_area_) {
struct disk_exception* merged_de =
reinterpret_cast<struct disk_exception*>((char*)merged_buffer + offset);
struct disk_exception* cow_de =
@@ -355,11 +358,11 @@
CHECK(cow_de->new_chunk == 0);
break;
} else {
- LOG(ERROR) << "Error in merge operation. Found invalid metadata";
- LOG(ERROR) << "merged_de-old-chunk: " << merged_de->old_chunk;
- LOG(ERROR) << "merged_de-new-chunk: " << merged_de->new_chunk;
- LOG(ERROR) << "cow_de-old-chunk: " << cow_de->old_chunk;
- LOG(ERROR) << "cow_de-new-chunk: " << cow_de->new_chunk;
+ SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata";
+ SNAP_LOG(ERROR) << "merged_de-old-chunk: " << merged_de->old_chunk;
+ SNAP_LOG(ERROR) << "merged_de-new-chunk: " << merged_de->new_chunk;
+ SNAP_LOG(ERROR) << "cow_de-old-chunk: " << cow_de->old_chunk;
+ SNAP_LOG(ERROR) << "cow_de-new-chunk: " << cow_de->new_chunk;
return -1;
}
}
@@ -384,19 +387,19 @@
if (!(cow_op->type == kCowReplaceOp || cow_op->type == kCowZeroOp ||
cow_op->type == kCowCopyOp)) {
- LOG(ERROR) << "Unknown operation-type found during merge: " << cow_op->type;
+ SNAP_LOG(ERROR) << "Unknown operation-type found during merge: " << cow_op->type;
return false;
}
merged_ops_cur_iter -= 1;
- LOG(DEBUG) << "Merge op found of type " << cow_op->type
- << "Pending-merge-ops: " << merged_ops_cur_iter;
+ SNAP_LOG(DEBUG) << "Merge op found of type " << cow_op->type
+ << "Pending-merge-ops: " << merged_ops_cur_iter;
cowop_iter_->Next();
}
if (cowop_iter_->Done()) {
CHECK(merged_ops_cur_iter == 0);
- LOG(DEBUG) << "All cow operations merged successfully in this cycle";
+ SNAP_LOG(DEBUG) << "All cow operations merged successfully in this cycle";
}
return true;
@@ -407,14 +410,15 @@
CowHeader header;
if (!reader_->GetHeader(&header)) {
- LOG(ERROR) << "Failed to get header";
+ SNAP_LOG(ERROR) << "Failed to get header";
return false;
}
// ChunkID to vector index
lldiv_t divresult = lldiv(chunk, stride);
CHECK(divresult.quot < vec_.size());
- LOG(DEBUG) << "ProcessMergeComplete: chunk: " << chunk << " Metadata-Index: " << divresult.quot;
+ SNAP_LOG(DEBUG) << "ProcessMergeComplete: chunk: " << chunk
+ << " Metadata-Index: " << divresult.quot;
int unmerged_exceptions = 0;
loff_t offset = GetMergeStartOffset(buffer, vec_[divresult.quot].get(), &unmerged_exceptions);
@@ -429,11 +433,11 @@
header.num_merge_ops += merged_ops_cur_iter;
reader_->UpdateMergeProgress(merged_ops_cur_iter);
if (!writer_->CommitMerge(merged_ops_cur_iter)) {
- LOG(ERROR) << "CommitMerge failed...";
+ SNAP_LOG(ERROR) << "CommitMerge failed...";
return false;
}
- LOG(DEBUG) << "Merge success";
+ SNAP_LOG(DEBUG) << "Merge success";
return true;
}
@@ -513,21 +517,21 @@
bool prev_copy_op = false;
bool metadata_found = false;
- LOG(DEBUG) << "ReadMetadata Start...";
+ SNAP_LOG(DEBUG) << "ReadMetadata Start...";
if (!reader_->Parse(cow_fd_)) {
- LOG(ERROR) << "Failed to parse";
+ SNAP_LOG(ERROR) << "Failed to parse";
return false;
}
if (!reader_->GetHeader(&header)) {
- LOG(ERROR) << "Failed to get header";
+ SNAP_LOG(ERROR) << "Failed to get header";
return false;
}
CHECK(header.block_size == BLOCK_SIZE);
- LOG(DEBUG) << "Merge-ops: " << header.num_merge_ops;
+ SNAP_LOG(DEBUG) << "Merge-ops: " << header.num_merge_ops;
writer_ = std::make_unique<CowWriter>(options);
writer_->InitializeMerge(cow_fd_.get(), &header);
@@ -563,7 +567,7 @@
if (!(cow_op->type == kCowReplaceOp || cow_op->type == kCowZeroOp ||
cow_op->type == kCowCopyOp)) {
- LOG(ERROR) << "Unknown operation-type found: " << cow_op->type;
+ SNAP_LOG(ERROR) << "Unknown operation-type found: " << cow_op->type;
return false;
}
@@ -578,7 +582,7 @@
de->old_chunk = cow_op->new_block;
de->new_chunk = next_free;
- LOG(DEBUG) << "Old-chunk: " << de->old_chunk << "New-chunk: " << de->new_chunk;
+ SNAP_LOG(DEBUG) << "Old-chunk: " << de->old_chunk << "New-chunk: " << de->new_chunk;
// Store operation pointer.
chunk_map_[next_free] = cow_op;
@@ -602,7 +606,7 @@
if (cowop_riter_->Done()) {
vec_.push_back(std::move(de_ptr));
- LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size();
+ SNAP_LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size();
}
}
@@ -614,12 +618,12 @@
// is aware that merge is completed.
if (num_ops || !metadata_found) {
vec_.push_back(std::move(de_ptr));
- LOG(DEBUG) << "ReadMetadata() completed. Partially filled area num_ops: " << num_ops
- << "Areas : " << vec_.size();
+ SNAP_LOG(DEBUG) << "ReadMetadata() completed. Partially filled area num_ops: " << num_ops
+ << "Areas : " << vec_.size();
}
- LOG(DEBUG) << "ReadMetadata() completed. chunk_id: " << next_free
- << "Num Sector: " << ChunkToSector(next_free);
+ SNAP_LOG(DEBUG) << "ReadMetadata() completed. chunk_id: " << next_free
+ << "Num Sector: " << ChunkToSector(next_free);
// Initialize the iterator for merging
cowop_iter_ = reader_->GetOpIter();
@@ -643,7 +647,7 @@
// us the sector number for which IO is issued by dm-snapshot device
bool Snapuserd::ReadDmUserHeader() {
if (!android::base::ReadFully(ctrl_fd_, bufsink_.GetBufPtr(), sizeof(struct dm_user_header))) {
- PLOG(ERROR) << "ReadDmUserHeader failed";
+ SNAP_PLOG(ERROR) << "Control-read failed";
return false;
}
@@ -654,7 +658,7 @@
bool Snapuserd::WriteDmUserPayload(size_t size) {
if (!android::base::WriteFully(ctrl_fd_, bufsink_.GetBufPtr(),
sizeof(struct dm_user_header) + size)) {
- PLOG(ERROR) << "Write to dm-user failed";
+ SNAP_PLOG(ERROR) << "Write to dm-user failed";
return false;
}
@@ -663,7 +667,7 @@
bool Snapuserd::ReadDmUserPayload(void* buffer, size_t size) {
if (!android::base::ReadFully(ctrl_fd_, buffer, size)) {
- PLOG(ERROR) << "ReadDmUserPayload failed";
+ SNAP_PLOG(ERROR) << "ReadDmUserPayload failed";
return false;
}
@@ -673,7 +677,7 @@
bool Snapuserd::InitCowDevice() {
cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
if (cow_fd_ < 0) {
- PLOG(ERROR) << "Open Failed: " << cow_device_;
+ SNAP_PLOG(ERROR) << "Open Failed: " << cow_device_;
return false;
}
@@ -690,13 +694,13 @@
bool Snapuserd::InitBackingAndControlDevice() {
backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY));
if (backing_store_fd_ < 0) {
- PLOG(ERROR) << "Open Failed: " << backing_store_device_;
+ SNAP_PLOG(ERROR) << "Open Failed: " << backing_store_device_;
return false;
}
ctrl_fd_.reset(open(control_device_.c_str(), O_RDWR));
if (ctrl_fd_ < 0) {
- PLOG(ERROR) << "Unable to open " << control_device_;
+ SNAP_PLOG(ERROR) << "Unable to open " << control_device_;
return false;
}
@@ -709,15 +713,15 @@
bufsink_.Clear();
if (!ReadDmUserHeader()) {
- LOG(ERROR) << "ReadDmUserHeader failed";
+ SNAP_LOG(ERROR) << "ReadDmUserHeader failed";
return false;
}
- LOG(DEBUG) << "msg->seq: " << std::hex << header->seq;
- LOG(DEBUG) << "msg->type: " << std::hex << header->type;
- LOG(DEBUG) << "msg->flags: " << std::hex << header->flags;
- LOG(DEBUG) << "msg->sector: " << std::hex << header->sector;
- LOG(DEBUG) << "msg->len: " << std::hex << header->len;
+ SNAP_LOG(DEBUG) << "msg->seq: " << std::hex << header->seq;
+ SNAP_LOG(DEBUG) << "msg->type: " << std::hex << header->type;
+ SNAP_LOG(DEBUG) << "msg->flags: " << std::hex << header->flags;
+ SNAP_LOG(DEBUG) << "msg->sector: " << std::hex << header->sector;
+ SNAP_LOG(DEBUG) << "msg->len: " << std::hex << header->len;
switch (header->type) {
case DM_USER_REQ_MAP_READ: {
@@ -736,7 +740,7 @@
CHECK(metadata_read_done_ == true);
CHECK(read_size == BLOCK_SIZE);
ConstructKernelCowHeader();
- LOG(DEBUG) << "Kernel header constructed";
+ SNAP_LOG(DEBUG) << "Kernel header constructed";
} else {
// Convert the sector number to a chunk ID.
//
@@ -747,22 +751,22 @@
if (chunk_map_.find(chunk) == chunk_map_.end()) {
if (!ReadDiskExceptions(chunk, read_size)) {
- LOG(ERROR) << "ReadDiskExceptions failed for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(ERROR) << "ReadDiskExceptions failed for chunk id: " << chunk
+ << "Sector: " << header->sector;
header->type = DM_USER_RESP_ERROR;
} else {
- LOG(DEBUG) << "ReadDiskExceptions success for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(DEBUG) << "ReadDiskExceptions success for chunk id: " << chunk
+ << "Sector: " << header->sector;
}
} else {
chunk_t num_chunks_read = (offset >> BLOCK_SHIFT);
if (!ReadData(chunk + num_chunks_read, read_size)) {
- LOG(ERROR) << "ReadData failed for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(ERROR) << "ReadData failed for chunk id: " << chunk
+ << "Sector: " << header->sector;
header->type = DM_USER_RESP_ERROR;
} else {
- LOG(DEBUG) << "ReadData success for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(DEBUG) << "ReadData success for chunk id: " << chunk
+ << "Sector: " << header->sector;
}
}
}
@@ -817,18 +821,18 @@
header->type = DM_USER_RESP_SUCCESS;
if (!ReadDmUserPayload(buffer, read_size)) {
- LOG(ERROR) << "ReadDmUserPayload failed for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(ERROR) << "ReadDmUserPayload failed for chunk id: " << chunk
+ << "Sector: " << header->sector;
header->type = DM_USER_RESP_ERROR;
}
if (header->type == DM_USER_RESP_SUCCESS && !ProcessMergeComplete(chunk, buffer)) {
- LOG(ERROR) << "ProcessMergeComplete failed for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(ERROR) << "ProcessMergeComplete failed for chunk id: " << chunk
+ << "Sector: " << header->sector;
header->type = DM_USER_RESP_ERROR;
} else {
- LOG(DEBUG) << "ProcessMergeComplete success for chunk id: " << chunk
- << "Sector: " << header->sector;
+ SNAP_LOG(DEBUG) << "ProcessMergeComplete success for chunk id: " << chunk
+ << "Sector: " << header->sector;
}
if (!WriteDmUserPayload(0)) {
diff --git a/fs_mgr/libsnapshot/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd_client.cpp
index a5d2061..7282bff 100644
--- a/fs_mgr/libsnapshot/snapuserd_client.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_client.cpp
@@ -54,25 +54,6 @@
return true;
}
-pid_t StartFirstStageSnapuserd() {
- pid_t pid = fork();
- if (pid < 0) {
- PLOG(ERROR) << "fork failed";
- return pid;
- }
- if (pid != 0) {
- return pid;
- }
-
- std::string arg0 = "/system/bin/snapuserd";
- std::string arg1 = kSnapuserdSocketFirstStage;
- char* const argv[] = {arg0.data(), arg1.data(), nullptr};
- if (execv(arg0.c_str(), argv) < 0) {
- PLOG(FATAL) << "execv failed";
- }
- return pid;
-}
-
SnapuserdClient::SnapuserdClient(android::base::unique_fd&& sockfd) : sockfd_(std::move(sockfd)) {}
static inline bool IsRetryErrno() {
@@ -229,5 +210,13 @@
return num_sectors;
}
+bool SnapuserdClient::DetachSnapuserd() {
+ if (!Sendmsg("detach")) {
+ LOG(ERROR) << "Failed to detach snapuserd.";
+ return false;
+ }
+ return true;
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index 9d57ab0..7a5cead 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -38,6 +38,7 @@
if (input == "stop") return DaemonOperations::STOP;
if (input == "query") return DaemonOperations::QUERY;
if (input == "delete") return DaemonOperations::DELETE;
+ if (input == "detach") return DaemonOperations::DETACH;
return DaemonOperations::INVALID;
}
@@ -72,19 +73,7 @@
void SnapuserdServer::ShutdownThreads() {
StopThreads();
-
- // Acquire the thread list within the lock.
- std::vector<std::shared_ptr<DmUserHandler>> dm_users;
- {
- std::lock_guard<std::mutex> guard(lock_);
- dm_users = std::move(dm_users_);
- }
-
- for (auto& client : dm_users) {
- auto& th = client->thread();
-
- if (th.joinable()) th.join();
- }
+ JoinAllThreads();
}
const std::string& DmUserHandler::GetMiscName() const {
@@ -214,6 +203,10 @@
}
return Sendmsg(fd, "success");
}
+ case DaemonOperations::DETACH: {
+ terminating_ = true;
+ return Sendmsg(fd, "success");
+ }
default: {
LOG(ERROR) << "Received unknown message type from client";
Sendmsg(fd, "fail");
@@ -234,7 +227,7 @@
LOG(INFO) << "Exiting thread for handler: " << handler->GetMiscName();
- // If the main thread called /emoveHandler, the handler was already removed
+ // If the main thread called RemoveHandler, the handler was already removed
// from within the lock, and calling RemoveHandler again has no effect.
RemoveHandler(handler->GetMiscName(), false);
}
@@ -286,9 +279,26 @@
}
}
}
+
+ JoinAllThreads();
return true;
}
+void SnapuserdServer::JoinAllThreads() {
+ // Acquire the thread list within the lock.
+ std::vector<std::shared_ptr<DmUserHandler>> dm_users;
+ {
+ std::lock_guard<std::mutex> guard(lock_);
+ dm_users = std::move(dm_users_);
+ }
+
+ for (auto& client : dm_users) {
+ auto& th = client->thread();
+
+ if (th.joinable()) th.join();
+ }
+}
+
void SnapuserdServer::AddWatchedFd(android::base::borrowed_fd fd) {
struct pollfd p = {};
p.fd = fd.get();
diff --git a/fs_mgr/tools/dmuserd.cpp b/fs_mgr/tools/dmuserd.cpp
index 92f5878..e50a4a2 100644
--- a/fs_mgr/tools/dmuserd.cpp
+++ b/fs_mgr/tools/dmuserd.cpp
@@ -76,7 +76,7 @@
static bool verbose = false;
-size_t write_all(int fd, void* buf, size_t len) {
+ssize_t write_all(int fd, void* buf, size_t len) {
char* buf_c = (char*)buf;
ssize_t total = 0;
ssize_t once;
@@ -94,7 +94,7 @@
return total;
}
-size_t read_all(int fd, void* buf, size_t len) {
+ssize_t read_all(int fd, void* buf, size_t len) {
char* buf_c = (char*)buf;
ssize_t total = 0;
ssize_t once;
diff --git a/init/README.md b/init/README.md
index ab6a885..bcbbfbb 100644
--- a/init/README.md
+++ b/init/README.md
@@ -451,6 +451,10 @@
exist. And it will be truncated if dst file is a normal regular file and
already exists.
+`copy_per_line <src> <dst>`
+> Copies a file line by line. Similar to copy, but useful for dst is a sysfs node
+ that doesn't handle multiple lines of data.
+
`domainname <name>`
> Set the domain name.
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index 8db9793..9c2a7bb 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -40,8 +40,8 @@
return InitMiscDevice("device-mapper");
}
-bool BlockDevInitializer::InitDmUser() {
- return InitMiscDevice("dm-user");
+bool BlockDevInitializer::InitDmUser(const std::string& name) {
+ return InitMiscDevice("dm-user!" + name);
}
bool BlockDevInitializer::InitMiscDevice(const std::string& name) {
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index b8dd3f1..79fe4ec 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -27,7 +27,7 @@
BlockDevInitializer();
bool InitDeviceMapper();
- bool InitDmUser();
+ bool InitDmUser(const std::string& name);
bool InitDevices(std::set<std::string> devices);
bool InitDmDevice(const std::string& device);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index d00d1b1..b235d2f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -88,6 +88,7 @@
using android::base::Basename;
using android::base::SetProperty;
+using android::base::Split;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -968,6 +969,23 @@
return {};
}
+static Result<void> do_copy_per_line(const BuiltinArguments& args) {
+ std::string file_contents;
+ if (!android::base::ReadFileToString(args[1], &file_contents, true)) {
+ return Error() << "Could not read input file '" << args[1] << "'";
+ }
+ auto lines = Split(file_contents, "\n");
+ for (const auto& line : lines) {
+ auto result = WriteFile(args[2], line);
+ if (!result.ok()) {
+ LOG(VERBOSE) << "Could not write to output file '" << args[2] << "' with '" << line
+ << "' : " << result.error();
+ }
+ }
+
+ return {};
+}
+
static Result<void> do_chown(const BuiltinArguments& args) {
auto uid = DecodeUid(args[1]);
if (!uid.ok()) {
@@ -1366,6 +1384,7 @@
{"class_start_post_data", {1, 1, {false, do_class_start_post_data}}},
{"class_stop", {1, 1, {false, do_class_stop}}},
{"copy", {2, 2, {true, do_copy}}},
+ {"copy_per_line", {2, 2, {true, do_copy_per_line}}},
{"domainname", {1, 1, {true, do_domainname}}},
{"enable", {1, 1, {false, do_enable}}},
{"exec", {1, kMax, {false, do_exec}}},
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 91aaffd..83a32e7 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -117,7 +117,7 @@
auto dst_dir = android::base::Dirname(dst);
std::error_code ec;
- if (!fs::create_directories(dst_dir, ec)) {
+ if (!fs::create_directories(dst_dir, ec) && !!ec) {
LOG(FATAL) << "Cannot create " << dst_dir << ": " << ec.message();
}
if (rename(src, dst) != 0) {
@@ -315,7 +315,7 @@
std::string dest = GetRamdiskPropForSecondStage();
std::string dir = android::base::Dirname(dest);
std::error_code ec;
- if (!fs::create_directories(dir, ec)) {
+ if (!fs::create_directories(dir, ec) && !!ec) {
LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message();
}
if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) {
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index b7d50cf..a0511cc 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -343,6 +343,15 @@
if (!InitRequiredDevices({"userdata"})) {
return false;
}
+ sm->SetUeventRegenCallback([this](const std::string& device) -> bool {
+ if (android::base::StartsWith(device, "/dev/block/dm-")) {
+ return block_dev_init_.InitDmDevice(device);
+ }
+ if (android::base::StartsWith(device, "/dev/dm-user/")) {
+ return block_dev_init_.InitDmUser(android::base::Basename(device));
+ }
+ return block_dev_init_.InitDevices({device});
+ });
return sm->CreateLogicalAndSnapshotPartitions(super_path_);
}
}
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index ef9a451..db127d3 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -25,6 +25,8 @@
#include <fstream>
#include <iostream>
#include <iterator>
+#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -51,6 +53,7 @@
using namespace std::literals;
+using android::base::EndsWith;
using android::base::ParseInt;
using android::base::ReadFileToString;
using android::base::Split;
@@ -61,6 +64,10 @@
static std::vector<std::string> passwd_files;
+// NOTE: Keep this in sync with the order used by init.cpp LoadBootScripts()
+static const std::vector<std::string> partition_search_order =
+ std::vector<std::string>({"system", "system_ext", "odm", "vendor", "product"});
+
static std::vector<std::pair<std::string, int>> GetVendorPasswd(const std::string& passwd_file) {
std::string passwd;
if (!ReadFileToString(passwd_file, &passwd)) {
@@ -148,13 +155,24 @@
#include "generated_stub_builtin_function_map.h"
void PrintUsage() {
- std::cout << "usage: host_init_verifier [options] <init rc file>\n"
- "\n"
- "Tests an init script for correctness\n"
- "\n"
- "-p FILE\tSearch this passwd file for users and groups\n"
- "--property_contexts=FILE\t Use this file for property_contexts\n"
- << std::endl;
+ fprintf(stdout, R"(usage: host_init_verifier [options]
+
+Tests init script(s) for correctness.
+
+Generic options:
+ -p FILE Search this passwd file for users and groups.
+ --property_contexts=FILE Use this file for property_contexts.
+
+Single script mode options:
+ [init rc file] Positional argument; test this init script.
+
+Multiple script mode options:
+ --out_system=DIR Path to the output product directory for the system partition.
+ --out_system_ext=DIR Path to the output product directory for the system_ext partition.
+ --out_odm=DIR Path to the output product directory for the odm partition.
+ --out_vendor=DIR Path to the output product directory for the vendor partition.
+ --out_product=DIR Path to the output product directory for the product partition.
+)");
}
Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy() {
@@ -203,12 +221,18 @@
android::base::SetMinimumLogSeverity(android::base::ERROR);
auto property_infos = std::vector<PropertyInfoEntry>();
+ std::map<std::string, std::string> partition_map;
while (true) {
static const char kPropertyContexts[] = "property-contexts=";
static const struct option long_options[] = {
{"help", no_argument, nullptr, 'h'},
{kPropertyContexts, required_argument, nullptr, 0},
+ {"out_system", required_argument, nullptr, 0},
+ {"out_system_ext", required_argument, nullptr, 0},
+ {"out_odm", required_argument, nullptr, 0},
+ {"out_vendor", required_argument, nullptr, 0},
+ {"out_product", required_argument, nullptr, 0},
{nullptr, 0, nullptr, 0},
};
@@ -224,6 +248,16 @@
if (long_options[option_index].name == kPropertyContexts) {
HandlePropertyContexts(optarg, &property_infos);
}
+ for (const auto& p : partition_search_order) {
+ if (long_options[option_index].name == "out_" + p) {
+ if (partition_map.find(p) != partition_map.end()) {
+ PrintUsage();
+ return EXIT_FAILURE;
+ }
+ partition_map[p] =
+ EndsWith(optarg, "/") ? optarg : std::string(optarg) + "/";
+ }
+ }
break;
case 'h':
PrintUsage();
@@ -240,7 +274,9 @@
argc -= optind;
argv += optind;
- if (argc != 1) {
+ // If provided, use the partition map to check multiple init rc files.
+ // Otherwise, check a single init rc file.
+ if ((!partition_map.empty() && argc != 0) || (partition_map.empty() && argc != 1)) {
PrintUsage();
return EXIT_FAILURE;
}
@@ -262,24 +298,42 @@
property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_contexts.c_str());
+ if (!partition_map.empty()) {
+ std::vector<std::string> vendor_prefixes;
+ for (const auto& partition : {"vendor", "odm"}) {
+ if (partition_map.find(partition) != partition_map.end()) {
+ vendor_prefixes.push_back(partition_map.at(partition));
+ }
+ }
+ InitializeHostSubcontext(vendor_prefixes);
+ }
+
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
Action::set_function_map(&function_map);
ActionManager& am = ActionManager::GetInstance();
ServiceList& sl = ServiceList::GetInstance();
Parser parser;
- parser.AddSectionParser("service", std::make_unique<ServiceParser>(
- &sl, nullptr, *interface_inheritance_hierarchy_map));
- parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+ parser.AddSectionParser("service",
+ std::make_unique<ServiceParser>(&sl, GetSubcontext(),
+ *interface_inheritance_hierarchy_map));
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, GetSubcontext()));
parser.AddSectionParser("import", std::make_unique<HostImportParser>());
- if (!parser.ParseConfigFileInsecure(*argv)) {
- LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
- return EXIT_FAILURE;
+ if (!partition_map.empty()) {
+ for (const auto& p : partition_search_order) {
+ if (partition_map.find(p) != partition_map.end()) {
+ parser.ParseConfig(partition_map.at(p) + "etc/init");
+ }
+ }
+ } else {
+ if (!parser.ParseConfigFileInsecure(*argv)) {
+ LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
+ return EXIT_FAILURE;
+ }
}
size_t failures = parser.parse_error_count() + am.CheckAllCommands() + sl.CheckAllCommands();
if (failures > 0) {
- LOG(ERROR) << "Failed to parse init script '" << *argv << "' with " << failures
- << " errors";
+ LOG(ERROR) << "Failed to parse init scripts with " << failures << " error(s).";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
diff --git a/init/init.cpp b/init/init.cpp
index c6f2066..1d0a9dc 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -875,13 +875,13 @@
SetProperty(gsi::kGsiInstalledProp, is_installed);
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
- am.QueueBuiltinAction(TransitionSnapuserdAction, "TransitionSnapuserd");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
am.QueueBuiltinAction(TestPerfEventSelinuxAction, "TestPerfEventSelinux");
am.QueueEventTrigger("early-init");
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
+ am.QueueBuiltinAction(TransitionSnapuserdAction, "TransitionSnapuserd");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
diff --git a/init/service.cpp b/init/service.cpp
index 7b98392..766eb5d 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -154,6 +154,7 @@
.priority = 0},
namespaces_{.flags = namespace_flags},
seclabel_(seclabel),
+ subcontext_(subcontext_for_restart_commands),
onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
"onrestart", {}),
oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
diff --git a/init/service.h b/init/service.h
index bc5c90f..aee1e5d 100644
--- a/init/service.h
+++ b/init/service.h
@@ -137,6 +137,7 @@
flags_ &= ~SVC_ONESHOT;
}
}
+ Subcontext* subcontext() const { return subcontext_; }
private:
void NotifyStateChange(const std::string& new_state) const;
@@ -168,6 +169,7 @@
std::vector<FileDescriptor> files_;
std::vector<std::pair<std::string, std::string>> environment_vars_;
+ Subcontext* subcontext_;
Action onrestart_; // Commands to execute on restart.
std::vector<std::string> writepid_files_;
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 97621da..57c311a 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -657,6 +657,14 @@
<< "' with a config in APEX";
}
+ std::string context = service_->subcontext() ? service_->subcontext()->context() : "";
+ std::string old_context =
+ old_service->subcontext() ? old_service->subcontext()->context() : "";
+ if (context != old_context) {
+ return Error() << "service '" << service_->name() << "' overrides another service "
+ << "across the treble boundary.";
+ }
+
service_list_->RemoveService(*old_service);
old_service = nullptr;
}
diff --git a/init/service_utils.h b/init/service_utils.h
index e74f8c1..1e0b4bd 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -37,6 +37,8 @@
Descriptor(const std::string& name, android::base::unique_fd fd)
: name_(name), fd_(std::move(fd)){};
+ // Publish() unsets FD_CLOEXEC from the FD and publishes its name via setenv(). It should be
+ // called when starting a service after fork() and before exec().
void Publish() const;
private:
@@ -53,6 +55,9 @@
std::string context;
bool passcred = false;
+ // Create() creates the named unix domain socket in /dev/socket and returns a Descriptor object.
+ // It should be called when starting a service, before calling fork(), such that the socket is
+ // synchronously created before starting any other services, which may depend on it.
Result<Descriptor> Create(const std::string& global_context) const;
};
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index dc2455e..f1fbffe 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -342,6 +342,9 @@
new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
}
}
+void InitializeHostSubcontext(std::vector<std::string> vendor_prefixes) {
+ subcontext.reset(new Subcontext(vendor_prefixes, kVendorContext, /*host=*/true));
+}
Subcontext* GetSubcontext() {
return subcontext.get();
diff --git a/init/subcontext.h b/init/subcontext.h
index 788d3be..cb4138e 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -36,9 +36,11 @@
class Subcontext {
public:
- Subcontext(std::vector<std::string> path_prefixes, std::string context)
+ Subcontext(std::vector<std::string> path_prefixes, std::string context, bool host = false)
: path_prefixes_(std::move(path_prefixes)), context_(std::move(context)), pid_(0) {
- Fork();
+ if (!host) {
+ Fork();
+ }
}
Result<void> Execute(const std::vector<std::string>& args);
@@ -61,6 +63,7 @@
int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map);
void InitializeSubcontext();
+void InitializeHostSubcontext(std::vector<std::string> vendor_prefixes);
Subcontext* GetSubcontext();
bool SubcontextChildReap(pid_t pid);
void SubcontextTerminate();
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 31e1679..79c3abc 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -203,9 +203,14 @@
CAP_MASK_LONG(CAP_SETGID),
"system/bin/simpleperf_app_runner" },
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/e2fsck" },
- { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" },
+#ifdef __LP64__
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/linker64" },
+#else
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/linker" },
+#endif
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/resize2fs" },
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/snapuserd" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/libprocessgroup/profiles/Android.bp b/libprocessgroup/profiles/Android.bp
index c371ef7..a496237 100644
--- a/libprocessgroup/profiles/Android.bp
+++ b/libprocessgroup/profiles/Android.bp
@@ -15,6 +15,11 @@
prebuilt_etc {
name: "cgroups.json",
src: "cgroups.json",
+ required: [
+ "cgroups_28.json",
+ "cgroups_29.json",
+ "cgroups_30.json",
+ ],
}
prebuilt_etc {
@@ -25,8 +30,49 @@
}
prebuilt_etc {
+ name: "cgroups_28.json",
+ src: "cgroups_28.json",
+ sub_dir: "task_profiles",
+}
+
+prebuilt_etc {
+ name: "cgroups_29.json",
+ src: "cgroups_29.json",
+ sub_dir: "task_profiles",
+}
+
+prebuilt_etc {
+ name: "cgroups_30.json",
+ src: "cgroups_30.json",
+ sub_dir: "task_profiles",
+}
+
+prebuilt_etc {
name: "task_profiles.json",
src: "task_profiles.json",
+ required: [
+ "task_profiles_28.json",
+ "task_profiles_29.json",
+ "task_profiles_30.json",
+ ],
+}
+
+prebuilt_etc {
+ name: "task_profiles_28.json",
+ src: "task_profiles_28.json",
+ sub_dir: "task_profiles",
+}
+
+prebuilt_etc {
+ name: "task_profiles_29.json",
+ src: "task_profiles_29.json",
+ sub_dir: "task_profiles",
+}
+
+prebuilt_etc {
+ name: "task_profiles_30.json",
+ src: "task_profiles_30.json",
+ sub_dir: "task_profiles",
}
cc_defaults {
diff --git a/libprocessgroup/profiles/cgroups_28.json b/libprocessgroup/profiles/cgroups_28.json
new file mode 100644
index 0000000..4518487
--- /dev/null
+++ b/libprocessgroup/profiles/cgroups_28.json
@@ -0,0 +1,59 @@
+{
+ "Cgroups": [
+ {
+ "Controller": "blkio",
+ "Path": "/dev/blkio",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpu",
+ "Path": "/dev/cpuctl",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpuacct",
+ "Path": "/acct",
+ "Mode": "0555"
+ },
+ {
+ "Controller": "cpuset",
+ "Path": "/dev/cpuset",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "memory",
+ "Path": "/dev/memcg",
+ "Mode": "0700",
+ "UID": "root",
+ "GID": "system"
+ },
+ {
+ "Controller": "schedtune",
+ "Path": "/dev/stune",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ],
+ "Cgroups2": {
+ "Path": "/sys/fs/cgroup",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system",
+ "Controllers": [
+ {
+ "Controller": "freezer",
+ "Path": "freezer",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ]
+ }
+}
diff --git a/libprocessgroup/profiles/cgroups_29.json b/libprocessgroup/profiles/cgroups_29.json
new file mode 100644
index 0000000..4518487
--- /dev/null
+++ b/libprocessgroup/profiles/cgroups_29.json
@@ -0,0 +1,59 @@
+{
+ "Cgroups": [
+ {
+ "Controller": "blkio",
+ "Path": "/dev/blkio",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpu",
+ "Path": "/dev/cpuctl",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpuacct",
+ "Path": "/acct",
+ "Mode": "0555"
+ },
+ {
+ "Controller": "cpuset",
+ "Path": "/dev/cpuset",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "memory",
+ "Path": "/dev/memcg",
+ "Mode": "0700",
+ "UID": "root",
+ "GID": "system"
+ },
+ {
+ "Controller": "schedtune",
+ "Path": "/dev/stune",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ],
+ "Cgroups2": {
+ "Path": "/sys/fs/cgroup",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system",
+ "Controllers": [
+ {
+ "Controller": "freezer",
+ "Path": "freezer",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ]
+ }
+}
diff --git a/libprocessgroup/profiles/cgroups_30.json b/libprocessgroup/profiles/cgroups_30.json
new file mode 100644
index 0000000..4518487
--- /dev/null
+++ b/libprocessgroup/profiles/cgroups_30.json
@@ -0,0 +1,59 @@
+{
+ "Cgroups": [
+ {
+ "Controller": "blkio",
+ "Path": "/dev/blkio",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpu",
+ "Path": "/dev/cpuctl",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "cpuacct",
+ "Path": "/acct",
+ "Mode": "0555"
+ },
+ {
+ "Controller": "cpuset",
+ "Path": "/dev/cpuset",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ },
+ {
+ "Controller": "memory",
+ "Path": "/dev/memcg",
+ "Mode": "0700",
+ "UID": "root",
+ "GID": "system"
+ },
+ {
+ "Controller": "schedtune",
+ "Path": "/dev/stune",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ],
+ "Cgroups2": {
+ "Path": "/sys/fs/cgroup",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system",
+ "Controllers": [
+ {
+ "Controller": "freezer",
+ "Path": "freezer",
+ "Mode": "0755",
+ "UID": "system",
+ "GID": "system"
+ }
+ ]
+ }
+}
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index ea0064f..b528fa5 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -100,7 +100,7 @@
"Params":
{
"Controller": "cpu",
- "Path": ""
+ "Path": "system"
}
}
]
diff --git a/libprocessgroup/profiles/task_profiles_28.json b/libprocessgroup/profiles/task_profiles_28.json
new file mode 100644
index 0000000..142b0ba
--- /dev/null
+++ b/libprocessgroup/profiles/task_profiles_28.json
@@ -0,0 +1,627 @@
+{
+ "Attributes": [
+ {
+ "Name": "LowCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "background/cpus"
+ },
+ {
+ "Name": "HighCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "foreground/cpus"
+ },
+ {
+ "Name": "MaxCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "top-app/cpus"
+ },
+ {
+ "Name": "MemLimit",
+ "Controller": "memory",
+ "File": "memory.limit_in_bytes"
+ },
+ {
+ "Name": "MemSoftLimit",
+ "Controller": "memory",
+ "File": "memory.soft_limit_in_bytes"
+ },
+ {
+ "Name": "MemSwappiness",
+ "Controller": "memory",
+ "File": "memory.swappiness"
+ },
+ {
+ "Name": "STuneBoost",
+ "Controller": "schedtune",
+ "File": "schedtune.boost"
+ },
+ {
+ "Name": "STunePreferIdle",
+ "Controller": "schedtune",
+ "File": "schedtune.prefer_idle"
+ },
+ {
+ "Name": "UClampMin",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.min"
+ },
+ {
+ "Name": "UClampMax",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.max"
+ },
+ {
+ "Name": "FreezerState",
+ "Controller": "freezer",
+ "File": "cgroup.freeze"
+ }
+ ],
+
+ "Profiles": [
+ {
+ "Name": "HighEnergySaving",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Frozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Unfrozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": "../"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "RealtimePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "rt"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CameraServicePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NNApiHALPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "nnapi-hal"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CpuPolicySpread",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "1"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CpuPolicyPack",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "VrKernelCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/performance"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/performance"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityMax",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system-background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ServiceCapacityRestricted",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "restricted"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CameraServiceCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "TimerSlackHigh",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "40000000"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "TimerSlackNormal",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "50000"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "PerfBoost",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "50%",
+ "Clamp": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "PerfClamp",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "0",
+ "Clamp": "30%"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "16MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "150"
+
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "512MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "100"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "SystemMemoryProcess",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "memory",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerDisabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerEnabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "1"
+ }
+ }
+ ]
+ }
+ ],
+
+ "AggregateProfiles": [
+ {
+ "Name": "SCHED_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "SCHED_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_RT_APP",
+ "Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "ProcessCapacityLow", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "CPUSET_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "ProcessCapacityMax", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_SYSTEM",
+ "Profiles": [ "ServiceCapacityLow", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_RESTRICTED",
+ "Profiles": [ "ServiceCapacityRestricted", "TimerSlackNormal" ]
+ }
+ ]
+}
diff --git a/libprocessgroup/profiles/task_profiles_29.json b/libprocessgroup/profiles/task_profiles_29.json
new file mode 100644
index 0000000..142b0ba
--- /dev/null
+++ b/libprocessgroup/profiles/task_profiles_29.json
@@ -0,0 +1,627 @@
+{
+ "Attributes": [
+ {
+ "Name": "LowCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "background/cpus"
+ },
+ {
+ "Name": "HighCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "foreground/cpus"
+ },
+ {
+ "Name": "MaxCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "top-app/cpus"
+ },
+ {
+ "Name": "MemLimit",
+ "Controller": "memory",
+ "File": "memory.limit_in_bytes"
+ },
+ {
+ "Name": "MemSoftLimit",
+ "Controller": "memory",
+ "File": "memory.soft_limit_in_bytes"
+ },
+ {
+ "Name": "MemSwappiness",
+ "Controller": "memory",
+ "File": "memory.swappiness"
+ },
+ {
+ "Name": "STuneBoost",
+ "Controller": "schedtune",
+ "File": "schedtune.boost"
+ },
+ {
+ "Name": "STunePreferIdle",
+ "Controller": "schedtune",
+ "File": "schedtune.prefer_idle"
+ },
+ {
+ "Name": "UClampMin",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.min"
+ },
+ {
+ "Name": "UClampMax",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.max"
+ },
+ {
+ "Name": "FreezerState",
+ "Controller": "freezer",
+ "File": "cgroup.freeze"
+ }
+ ],
+
+ "Profiles": [
+ {
+ "Name": "HighEnergySaving",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Frozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Unfrozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": "../"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "RealtimePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "rt"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CameraServicePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NNApiHALPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "nnapi-hal"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CpuPolicySpread",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "1"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CpuPolicyPack",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "VrKernelCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/performance"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/performance"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityMax",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system-background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ServiceCapacityRestricted",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "restricted"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CameraServiceCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "TimerSlackHigh",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "40000000"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "TimerSlackNormal",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "50000"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "PerfBoost",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "50%",
+ "Clamp": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "PerfClamp",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "0",
+ "Clamp": "30%"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "16MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "150"
+
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "512MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "100"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "SystemMemoryProcess",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "memory",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerDisabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerEnabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "1"
+ }
+ }
+ ]
+ }
+ ],
+
+ "AggregateProfiles": [
+ {
+ "Name": "SCHED_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "SCHED_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_RT_APP",
+ "Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "ProcessCapacityLow", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "CPUSET_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "ProcessCapacityMax", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_SYSTEM",
+ "Profiles": [ "ServiceCapacityLow", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_RESTRICTED",
+ "Profiles": [ "ServiceCapacityRestricted", "TimerSlackNormal" ]
+ }
+ ]
+}
diff --git a/libprocessgroup/profiles/task_profiles_30.json b/libprocessgroup/profiles/task_profiles_30.json
new file mode 100644
index 0000000..142b0ba
--- /dev/null
+++ b/libprocessgroup/profiles/task_profiles_30.json
@@ -0,0 +1,627 @@
+{
+ "Attributes": [
+ {
+ "Name": "LowCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "background/cpus"
+ },
+ {
+ "Name": "HighCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "foreground/cpus"
+ },
+ {
+ "Name": "MaxCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "top-app/cpus"
+ },
+ {
+ "Name": "MemLimit",
+ "Controller": "memory",
+ "File": "memory.limit_in_bytes"
+ },
+ {
+ "Name": "MemSoftLimit",
+ "Controller": "memory",
+ "File": "memory.soft_limit_in_bytes"
+ },
+ {
+ "Name": "MemSwappiness",
+ "Controller": "memory",
+ "File": "memory.swappiness"
+ },
+ {
+ "Name": "STuneBoost",
+ "Controller": "schedtune",
+ "File": "schedtune.boost"
+ },
+ {
+ "Name": "STunePreferIdle",
+ "Controller": "schedtune",
+ "File": "schedtune.prefer_idle"
+ },
+ {
+ "Name": "UClampMin",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.min"
+ },
+ {
+ "Name": "UClampMax",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.max"
+ },
+ {
+ "Name": "FreezerState",
+ "Controller": "freezer",
+ "File": "cgroup.freeze"
+ }
+ ],
+
+ "Profiles": [
+ {
+ "Name": "HighEnergySaving",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Frozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Unfrozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": "../"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "RealtimePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "rt"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CameraServicePerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NNApiHALPerformance",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "schedtune",
+ "Path": "nnapi-hal"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CpuPolicySpread",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "1"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "CpuPolicyPack",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "STunePreferIdle",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "VrKernelCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrServiceCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system/performance"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "VrProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "application/performance"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ProcessCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityNormal",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityHigh",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "foreground"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ProcessCapacityMax",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "top-app"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "ServiceCapacityLow",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "system-background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "ServiceCapacityRestricted",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "restricted"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "CameraServiceCapacity",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "cpuset",
+ "Path": "camera-daemon"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": "background"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "NormalIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
+ "Name": "MaxIoPriority",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "blkio",
+ "Path": ""
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "TimerSlackHigh",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "40000000"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "TimerSlackNormal",
+ "Actions": [
+ {
+ "Name": "SetTimerSlack",
+ "Params":
+ {
+ "Slack": "50000"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "PerfBoost",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "50%",
+ "Clamp": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "PerfClamp",
+ "Actions": [
+ {
+ "Name": "SetClamps",
+ "Params":
+ {
+ "Boost": "0",
+ "Clamp": "30%"
+ }
+ }
+ ]
+ },
+
+ {
+ "Name": "LowMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "16MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "150"
+
+ }
+ }
+ ]
+ },
+ {
+ "Name": "HighMemoryUsage",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSoftLimit",
+ "Value": "512MB"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "MemSwappiness",
+ "Value": "100"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "SystemMemoryProcess",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "memory",
+ "Path": "system"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerDisabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "0"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "FreezerEnabled",
+ "Actions": [
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "FreezerState",
+ "Value": "1"
+ }
+ }
+ ]
+ }
+ ],
+
+ "AggregateProfiles": [
+ {
+ "Name": "SCHED_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "SCHED_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "SCHED_SP_RT_APP",
+ "Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_DEFAULT",
+ "Profiles": [ "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_BACKGROUND",
+ "Profiles": [ "HighEnergySaving", "ProcessCapacityLow", "LowIoPriority", "TimerSlackHigh" ]
+ },
+ {
+ "Name": "CPUSET_SP_FOREGROUND",
+ "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "HighIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_TOP_APP",
+ "Profiles": [ "MaxPerformance", "ProcessCapacityMax", "MaxIoPriority", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_SYSTEM",
+ "Profiles": [ "ServiceCapacityLow", "TimerSlackNormal" ]
+ },
+ {
+ "Name": "CPUSET_SP_RESTRICTED",
+ "Profiles": [ "ServiceCapacityRestricted", "TimerSlackNormal" ]
+ }
+ ]
+}
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index 25f16a6..a53132e 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -45,7 +45,7 @@
#include "cgroup_descriptor.h"
-using android::base::GetBoolProperty;
+using android::base::GetUintProperty;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -55,6 +55,8 @@
static constexpr const char* CGROUPS_DESC_FILE = "/etc/cgroups.json";
static constexpr const char* CGROUPS_DESC_VENDOR_FILE = "/vendor/etc/cgroups.json";
+static constexpr const char* TEMPLATE_CGROUPS_DESC_API_FILE = "/etc/task_profiles/cgroups_%u.json";
+
static bool ChangeDirModeAndOwner(const std::string& path, mode_t mode, const std::string& uid,
const std::string& gid, bool permissive_mode = false) {
uid_t pw_uid = -1;
@@ -212,8 +214,20 @@
}
static bool ReadDescriptors(std::map<std::string, CgroupDescriptor>* descriptors) {
+ unsigned int api_level = GetUintProperty<unsigned int>("ro.product.first_api_level", 0);
+ std::string sys_cgroups_path = CGROUPS_DESC_FILE;
+
+ // load API-level specific system cgroups descriptors if available
+ if (api_level > 0) {
+ std::string api_cgroups_path =
+ android::base::StringPrintf(TEMPLATE_CGROUPS_DESC_API_FILE, api_level);
+ if (!access(api_cgroups_path.c_str(), F_OK) || errno != ENOENT) {
+ sys_cgroups_path = api_cgroups_path;
+ }
+ }
+
// load system cgroup descriptors
- if (!ReadDescriptorsFromFile(CGROUPS_DESC_FILE, descriptors)) {
+ if (!ReadDescriptorsFromFile(sys_cgroups_path, descriptors)) {
return false;
}
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 4e767db..db44228 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -23,6 +23,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/threads.h>
@@ -38,13 +39,17 @@
#endif
using android::base::GetThreadId;
+using android::base::GetUintProperty;
using android::base::StringPrintf;
using android::base::StringReplace;
using android::base::unique_fd;
using android::base::WriteStringToFile;
-#define TASK_PROFILE_DB_FILE "/etc/task_profiles.json"
-#define TASK_PROFILE_DB_VENDOR_FILE "/vendor/etc/task_profiles.json"
+static constexpr const char* TASK_PROFILE_DB_FILE = "/etc/task_profiles.json";
+static constexpr const char* TASK_PROFILE_DB_VENDOR_FILE = "/vendor/etc/task_profiles.json";
+
+static constexpr const char* TEMPLATE_TASK_PROFILE_API_FILE =
+ "/etc/task_profiles/task_profiles_%u.json";
void ProfileAttribute::Reset(const CgroupController& controller, const std::string& file_name) {
controller_ = controller;
@@ -386,9 +391,21 @@
}
TaskProfiles::TaskProfiles() {
+ unsigned int api_level = GetUintProperty<unsigned int>("ro.product.first_api_level", 0);
+ std::string sys_profiles_path = TASK_PROFILE_DB_FILE;
+
+ // load API-level specific system task profiles if available
+ if (api_level > 0) {
+ std::string api_profiles_path =
+ android::base::StringPrintf(TEMPLATE_TASK_PROFILE_API_FILE, api_level);
+ if (!access(api_profiles_path.c_str(), F_OK) || errno != ENOENT) {
+ sys_profiles_path = api_profiles_path;
+ }
+ }
+
// load system task profiles
- if (!Load(CgroupMap::GetInstance(), TASK_PROFILE_DB_FILE)) {
- LOG(ERROR) << "Loading " << TASK_PROFILE_DB_FILE << " for [" << getpid() << "] failed";
+ if (!Load(CgroupMap::GetInstance(), sys_profiles_path)) {
+ LOG(ERROR) << "Loading " << sys_profiles_path << " for [" << getpid() << "] failed";
}
// load vendor task profiles if the file exists
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index bf06bbc..860b9ae 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -4,6 +4,7 @@
name: "libsparse",
host_supported: true,
ramdisk_available: true,
+ vendor_ramdisk_available: true,
recovery_available: true,
unique_host_soname: true,
vendor_available: true,
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4219e32..52ba921 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -153,21 +153,56 @@
mkdir /dev/cpuctl/background
mkdir /dev/cpuctl/top-app
mkdir /dev/cpuctl/rt
+ mkdir /dev/cpuctl/system
chown system system /dev/cpuctl
chown system system /dev/cpuctl/foreground
chown system system /dev/cpuctl/background
chown system system /dev/cpuctl/top-app
chown system system /dev/cpuctl/rt
+ chown system system /dev/cpuctl/system
chown system system /dev/cpuctl/tasks
chown system system /dev/cpuctl/foreground/tasks
chown system system /dev/cpuctl/background/tasks
chown system system /dev/cpuctl/top-app/tasks
chown system system /dev/cpuctl/rt/tasks
+ chown system system /dev/cpuctl/system/tasks
chmod 0664 /dev/cpuctl/tasks
chmod 0664 /dev/cpuctl/foreground/tasks
chmod 0664 /dev/cpuctl/background/tasks
chmod 0664 /dev/cpuctl/top-app/tasks
chmod 0664 /dev/cpuctl/rt/tasks
+ chmod 0664 /dev/cpuctl/system/tasks
+
+ # Create a cpu group for NNAPI HAL processes
+ mkdir /dev/cpuctl/nnapi-hal
+ chown system system /dev/cpuctl/nnapi-hal
+ chown system system /dev/cpuctl/nnapi-hal/tasks
+ chmod 0664 /dev/cpuctl/nnapi-hal/tasks
+ write /dev/cpuctl/nnapi-hal/cpu.uclamp.min 1
+ write /dev/cpuctl/nnapi-hal/cpu.uclamp.latency_sensitive 1
+
+ # Android only use global RT throttling and doesn't use CONFIG_RT_GROUP_SCHED
+ # for RT group throttling. These values here are just to make sure RT threads
+ # can be migrated to those groups. These settings can be removed once we migrate
+ # to GKI kernel.
+ write /dev/cpuctl/cpu.rt_period_us 1000000
+ write /dev/cpuctl/cpu.rt_runtime_us 950000
+ # Surfaceflinger is in FG group so giving it a bit more
+ write /dev/cpuctl/foreground/cpu.rt_runtime_us 450000
+ write /dev/cpuctl/foreground/cpu.rt_period_us 1000000
+ write /dev/cpuctl/background/cpu.rt_runtime_us 100000
+ write /dev/cpuctl/background/cpu.rt_period_us 1000000
+ write /dev/cpuctl/top-app/cpu.rt_runtime_us 100000
+ write /dev/cpuctl/top-app/cpu.rt_period_us 1000000
+ write /dev/cpuctl/rt/cpu.rt_runtime_us 100000
+ write /dev/cpuctl/rt/cpu.rt_period_us 1000000
+ write /dev/cpuctl/system/cpu.rt_runtime_us 100000
+ write /dev/cpuctl/system/cpu.rt_period_us 1000000
+ write /dev/cpuctl/nnapi-hal/cpu.rt_runtime_us 100000
+ write /dev/cpuctl/nnapi-hal/cpu.rt_period_us 1000000
+
+ # Migrate root group to system subgroup
+ copy_per_line /dev/cpuctl/tasks /dev/cpuctl/system/tasks
# Create an stune group for NNAPI HAL processes
mkdir /dev/stune/nnapi-hal
@@ -177,14 +212,6 @@
write /dev/stune/nnapi-hal/schedtune.boost 1
write /dev/stune/nnapi-hal/schedtune.prefer_idle 1
- # cpuctl hierarchy for devices using utilclamp
- mkdir /dev/cpuctl/nnapi-hal
- chown system system /dev/cpuctl/nnapi-hal
- chown system system /dev/cpuctl/nnapi-hal/tasks
- chmod 0664 /dev/cpuctl/nnapi-hal/tasks
- write /dev/cpuctl/nnapi-hal/cpu.uclamp.min 1
- write /dev/cpuctl/nnapi-hal/cpu.uclamp.latency_sensitive 1
-
# Create blkio group and apply initial settings.
# This feature needs kernel to support it, and the
# device's init.rc must actually set the correct values.
@@ -275,8 +302,6 @@
write /proc/sys/vm/mmap_min_addr 32768
write /proc/sys/net/ipv4/ping_group_range "0 2147483647"
write /proc/sys/net/unix/max_dgram_qlen 600
- write /proc/sys/kernel/sched_rt_runtime_us 950000
- write /proc/sys/kernel/sched_rt_period_us 1000000
# Assign reasonable ceiling values for socket rcv/snd buffers.
# These should almost always be overridden by the target per the
@@ -298,13 +323,6 @@
# /proc/net/fib_trie leaks interface IP addresses
chmod 0400 /proc/net/fib_trie
- # Create cgroup mount points for process groups
- chown system system /dev/cpuctl
- chown system system /dev/cpuctl/tasks
- chmod 0666 /dev/cpuctl/tasks
- write /dev/cpuctl/cpu.rt_period_us 1000000
- write /dev/cpuctl/cpu.rt_runtime_us 950000
-
# sets up initial cpusets for ActivityManager
# this ensures that the cpusets are present and usable, but the device's
# init.rc must actually set the correct cpus
@@ -1151,3 +1169,7 @@
on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1
setprop sys.init.userspace_reboot.in_progress ""
+
+# Migrate tasks again in case kernel threads are created during boot
+on property:sys.boot_completed=1
+ copy_per_line /dev/cpuctl/tasks /dev/cpuctl/system/tasks
diff --git a/trusty/confirmationui/fuzz/Android.bp b/trusty/confirmationui/fuzz/Android.bp
new file mode 100644
index 0000000..0819c21
--- /dev/null
+++ b/trusty/confirmationui/fuzz/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2020 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.
+
+cc_fuzz {
+ name: "trusty_confirmationui_fuzzer",
+ defaults: ["trusty_fuzzer_defaults"],
+ srcs: ["fuzz.cpp"],
+}
diff --git a/trusty/confirmationui/fuzz/fuzz.cpp b/trusty/confirmationui/fuzz/fuzz.cpp
new file mode 100644
index 0000000..d285116
--- /dev/null
+++ b/trusty/confirmationui/fuzz/fuzz.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#undef NDEBUG
+
+#include <assert.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <trusty/fuzz/utils.h>
+#include <unistd.h>
+
+using android::trusty::fuzz::TrustyApp;
+
+#define TIPC_DEV "/dev/trusty-ipc-dev0"
+#define CONFIRMATIONUI_PORT "com.android.trusty.confirmationui"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ static uint8_t buf[TIPC_MAX_MSG_SIZE];
+
+ TrustyApp ta(TIPC_DEV, CONFIRMATIONUI_PORT);
+ auto ret = ta.Connect();
+ if (!ret.ok()) {
+ android::trusty::fuzz::Abort();
+ }
+
+ /* Send message to confirmationui server */
+ ret = ta.Write(data, size);
+ if (!ret.ok()) {
+ return -1;
+ }
+
+ /* Read message from confirmationui server */
+ ret = ta.Read(&buf, sizeof(buf));
+ if (!ret.ok()) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/trusty/fuzz/Android.bp b/trusty/fuzz/Android.bp
index 969431c..ac49751 100644
--- a/trusty/fuzz/Android.bp
+++ b/trusty/fuzz/Android.bp
@@ -14,10 +14,8 @@
cc_defaults {
name: "trusty_fuzzer_defaults",
- static_libs: [
- "libtrusty_fuzz_utils",
- ],
shared_libs: [
+ "libtrusty_fuzz_utils",
"libbase",
"liblog",
],
@@ -36,6 +34,7 @@
srcs: ["utils.cpp"],
export_include_dirs: ["include"],
shared_libs: [
+ "libtrusty_test",
"libbase",
"liblog",
],
diff --git a/trusty/fuzz/utils.cpp b/trusty/fuzz/utils.cpp
index 240afe7..f4cf0b6 100644
--- a/trusty/fuzz/utils.cpp
+++ b/trusty/fuzz/utils.cpp
@@ -25,6 +25,7 @@
#include <linux/uio.h>
#include <log/log_read.h>
#include <time.h>
+#include <trusty/tipc.h>
#include <iostream>
using android::base::ErrnoError;
@@ -32,9 +33,6 @@
using android::base::Result;
using android::base::unique_fd;
-#define TIPC_IOC_MAGIC 'r'
-#define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char*)
-
namespace {
const size_t kTimeoutSeconds = 5;
@@ -80,27 +78,14 @@
: tipc_dev_(tipc_dev), ta_port_(ta_port), ta_fd_(-1) {}
Result<void> TrustyApp::Connect() {
- /*
- * TODO: We can't use libtrusty because (yet)
- * (1) cc_fuzz can't deal with vendor components (b/170753563)
- * (2) We need non-blocking behavior to detect Trusty going down.
- * (we could implement the timeout in the fuzzing code though, as
- * it needs to be around the call to read())
- */
alarm(kTimeoutSeconds);
- int fd = open(tipc_dev_.c_str(), O_RDWR);
+ int fd = tipc_connect(tipc_dev_.c_str(), ta_port_.c_str());
alarm(0);
if (fd < 0) {
return ErrnoError() << "failed to open TIPC device: ";
}
ta_fd_.reset(fd);
- // This ioctl will time out in the kernel if it can't connect.
- int rc = TEMP_FAILURE_RETRY(ioctl(ta_fd_, TIPC_IOC_CONNECT, ta_port_.c_str()));
- if (rc < 0) {
- return ErrnoError() << "failed to connect to TIPC service: ";
- }
-
return {};
}
diff --git a/trusty/libtrusty/Android.bp b/trusty/libtrusty/Android.bp
index 8dba78d..708fdbd 100644
--- a/trusty/libtrusty/Android.bp
+++ b/trusty/libtrusty/Android.bp
@@ -12,10 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library {
- name: "libtrusty",
- vendor: true,
-
+cc_defaults {
+ name: "libtrusty_defaults",
srcs: ["trusty.c"],
export_include_dirs: ["include"],
cflags: [
@@ -25,3 +23,16 @@
shared_libs: ["liblog"],
}
+
+cc_library {
+ name: "libtrusty",
+ vendor: true,
+ defaults: ["libtrusty_defaults"],
+}
+
+// TODO(b/170753563): cc_fuzz can't deal with vendor components. Build libtrusty
+// for system.
+cc_test_library {
+ name: "libtrusty_test",
+ defaults: ["libtrusty_defaults"],
+}
diff --git a/trusty/trusty-test.mk b/trusty/trusty-test.mk
index dc4c962..74106ec 100644
--- a/trusty/trusty-test.mk
+++ b/trusty/trusty-test.mk
@@ -15,4 +15,5 @@
PRODUCT_PACKAGES += \
spiproxyd \
trusty_keymaster_set_attestation_key \
- keymaster_soft_attestation_keys.xml \
\ No newline at end of file
+ keymaster_soft_attestation_keys.xml \
+