Merge "libunwindstack: add simpleperf presumit test."
diff --git a/adb/Android.bp b/adb/Android.bp
index 3e8da8a..b39defe 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -730,39 +730,3 @@
"fastdeploy/testdata/sample.cd",
],
}
-
-prebuilt_etc {
- name: "com.android.adbd.ld.config.txt",
- src: "apex/ld.config.txt",
- filename: "ld.config.txt",
- installable: false,
-}
-
-apex {
- name: "com.android.adbd",
- manifest: "apex/apex_manifest.json",
-
- binaries: ["adbd"],
- prebuilts: ["com.android.adbd.init.rc", "com.android.adbd.ld.config.txt"],
-
- key: "com.android.adbd.key",
- certificate: ":com.android.adbd.certificate",
-}
-
-apex_key {
- name: "com.android.adbd.key",
- public_key: "apex/com.android.adbd.avbpubkey",
- private_key: "apex/com.android.adbd.pem",
-}
-
-android_app_certificate {
- name: "com.android.adbd.certificate",
- certificate: "apex/com.android.adbd",
-}
-
-prebuilt_etc {
- name: "com.android.adbd.init.rc",
- src: "apex/adbd.rc",
- filename: "init.rc",
- installable: false,
-}
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
new file mode 100644
index 0000000..40ea448
--- /dev/null
+++ b/adb/apex/Android.bp
@@ -0,0 +1,49 @@
+apex_defaults {
+ name: "com.android.adbd-defaults",
+
+ binaries: ["adbd"],
+ prebuilts: ["com.android.adbd.init.rc", "com.android.adbd.ld.config.txt"],
+
+ key: "com.android.adbd.key",
+ certificate: ":com.android.adbd.certificate",
+}
+
+apex {
+ name: "com.android.adbd",
+ defaults: ["com.android.adbd-defaults"],
+ manifest: "apex_manifest.json",
+}
+
+// adbd apex with INT_MAX version code, to allow for upgrade/rollback testing.
+apex {
+ name: "test_com.android.adbd",
+ defaults: ["com.android.adbd-defaults"],
+ manifest: "test_apex_manifest.json",
+ file_contexts: ":com.android.adbd-file_contexts",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "com.android.adbd.ld.config.txt",
+ src: "ld.config.txt",
+ filename: "ld.config.txt",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "com.android.adbd.init.rc",
+ src: "adbd.rc",
+ filename: "init.rc",
+ installable: false,
+}
+
+apex_key {
+ name: "com.android.adbd.key",
+ public_key: "com.android.adbd.avbpubkey",
+ private_key: "com.android.adbd.pem",
+}
+
+android_app_certificate {
+ name: "com.android.adbd.certificate",
+ certificate: "com.android.adbd",
+}
diff --git a/adb/apex/test_apex_manifest.json b/adb/apex/test_apex_manifest.json
new file mode 100644
index 0000000..7131977
--- /dev/null
+++ b/adb/apex/test_apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.adbd",
+ "version": 2147483647
+}
diff --git a/base/Android.bp b/base/Android.bp
index b25d0df..a32959b 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -33,6 +33,7 @@
cc_library_headers {
name: "libbase_headers",
vendor_available: true,
+ ramdisk_available: true,
recovery_available: true,
host_supported: true,
native_bridge_supported: true,
@@ -112,6 +113,7 @@
name: "libbase",
defaults: ["libbase_defaults"],
vendor_available: true,
+ ramdisk_available: true,
recovery_available: true,
host_supported: true,
native_bridge_supported: true,
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
index 030ef35e..b3f5adb 100644
--- a/base/include/android-base/expected.h
+++ b/base/include/android-base/expected.h
@@ -111,6 +111,7 @@
!(!std::is_convertible_v<const U&, T> ||
!std::is_convertible_v<const G&, E>) /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const expected<U, G>& rhs) {
if (rhs.has_value()) var_ = rhs.value();
else var_ = unexpected(rhs.error());
@@ -149,6 +150,7 @@
!(!std::is_convertible_v<const U&, T> ||
!std::is_convertible_v<const G&, E>) /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(expected<U, G>&& rhs) {
if (rhs.has_value()) var_ = std::move(rhs.value());
else var_ = unexpected(std::move(rhs.error()));
@@ -180,6 +182,7 @@
!std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
std::is_convertible_v<U&&, T> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(U&& v) : var_(std::in_place_index<0>, std::forward<U>(v)) {}
template <class U = T _ENABLE_IF(
@@ -195,6 +198,7 @@
std::is_constructible_v<E, const G&> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const unexpected<G>& e)
: var_(std::in_place_index<1>, e.value()) {}
@@ -209,6 +213,7 @@
std::is_constructible_v<E, G&&> &&
std::is_convertible_v<G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(unexpected<G>&& e)
: var_(std::in_place_index<1>, std::move(e.value())) {}
@@ -457,6 +462,7 @@
std::is_void_v<U> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const expected<U, G>& rhs) {
if (!rhs.has_value()) var_ = unexpected(rhs.error());
}
@@ -473,6 +479,7 @@
std::is_void_v<U> &&
std::is_convertible_v<const G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(expected<U, G>&& rhs) {
if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
}
@@ -489,6 +496,7 @@
std::is_constructible_v<E, const G&> &&
std::is_convertible_v<const G&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(const unexpected<G>& e)
: var_(std::in_place_index<1>, e.value()) {}
@@ -503,6 +511,7 @@
std::is_constructible_v<E, G&&> &&
std::is_convertible_v<G&&, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr expected(unexpected<G>&& e)
: var_(std::in_place_index<1>, std::move(e.value())) {}
@@ -640,6 +649,7 @@
std::is_constructible_v<E, Err> &&
!std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
!std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
template<class U, class... Args _ENABLE_IF(
@@ -660,6 +670,7 @@
!std::is_convertible_v<const unexpected<Err>, E> &&
std::is_convertible_v<Err, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(const unexpected<Err>& rhs)
: val_(rhs.value()) {}
@@ -690,6 +701,7 @@
!std::is_convertible_v<const unexpected<Err>, E> &&
std::is_convertible_v<Err, E> /* non-explicit */
)>
+ // NOLINTNEXTLINE(google-explicit-constructor)
constexpr unexpected(unexpected<Err>&& rhs)
: val_(std::move(rhs.value())) {}
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 7fd0182..cc162cd 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -115,7 +115,6 @@
void DefaultAborter(const char* abort_message);
-std::string GetDefaultTag();
void SetDefaultTag(const std::string& tag);
// We expose this even though it is the default because a user that wants to
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
index 1b763af..b6d26e7 100644
--- a/base/include/android-base/result.h
+++ b/base/include/android-base/result.h
@@ -90,6 +90,7 @@
ResultError(T&& message, int code) : message_(std::forward<T>(message)), code_(code) {}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator android::base::expected<T, ResultError>() {
return android::base::unexpected(ResultError(message_, code_));
}
@@ -118,9 +119,11 @@
class Error {
public:
Error() : errno_(0), append_errno_(false) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
Error(int errno_to_append) : errno_(errno_to_append), append_errno_(true) {}
template <typename T>
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator android::base::expected<T, ResultError>() {
return android::base::unexpected(ResultError(str(), errno_));
}
diff --git a/base/liblog_symbols.cpp b/base/liblog_symbols.cpp
index d0e2eaa..d5dfcd2 100644
--- a/base/liblog_symbols.cpp
+++ b/base/liblog_symbols.cpp
@@ -50,6 +50,7 @@
DLSYM(__android_log_default_aborter)
DLSYM(__android_log_set_minimum_priority);
DLSYM(__android_log_get_minimum_priority);
+ DLSYM(__android_log_set_default_tag);
#undef DLSYM
return real_liblog_functions;
@@ -72,6 +73,7 @@
.__android_log_default_aborter = __android_log_default_aborter,
.__android_log_set_minimum_priority = __android_log_set_minimum_priority,
.__android_log_get_minimum_priority = __android_log_get_minimum_priority,
+ .__android_log_set_default_tag = __android_log_set_default_tag,
};
}();
return liblog_functions;
diff --git a/base/liblog_symbols.h b/base/liblog_symbols.h
index c68fff6..d3134e9 100644
--- a/base/liblog_symbols.h
+++ b/base/liblog_symbols.h
@@ -38,6 +38,7 @@
void (*__android_log_default_aborter)(const char* abort_message);
int (*__android_log_set_minimum_priority)(int priority);
int (*__android_log_get_minimum_priority)();
+ void (*__android_log_set_default_tag)(const char* tag);
};
const std::optional<LibLogFunctions>& GetLibLogFunctions();
diff --git a/base/logging.cpp b/base/logging.cpp
index 508871d..a868706 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -211,26 +211,27 @@
return aborter;
}
+// Only used for Q fallback.
static std::recursive_mutex& TagLock() {
static auto& tag_lock = *new std::recursive_mutex();
return tag_lock;
}
+// Only used for Q fallback.
static std::string* gDefaultTag;
-std::string GetDefaultTag() {
- std::lock_guard<std::recursive_mutex> lock(TagLock());
- if (gDefaultTag == nullptr) {
- return "";
- }
- return *gDefaultTag;
-}
+
void SetDefaultTag(const std::string& tag) {
- std::lock_guard<std::recursive_mutex> lock(TagLock());
- if (gDefaultTag != nullptr) {
- delete gDefaultTag;
- gDefaultTag = nullptr;
- }
- if (!tag.empty()) {
- gDefaultTag = new std::string(tag);
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ liblog_functions->__android_log_set_default_tag(tag.c_str());
+ } else {
+ std::lock_guard<std::recursive_mutex> lock(TagLock());
+ if (gDefaultTag != nullptr) {
+ delete gDefaultTag;
+ gDefaultTag = nullptr;
+ }
+ if (!tag.empty()) {
+ gDefaultTag = new std::string(tag);
+ }
}
}
@@ -574,24 +575,18 @@
const char* message) {
static auto& liblog_functions = GetLibLogFunctions();
auto priority = LogSeverityToPriority(severity);
- if (tag == nullptr) {
- std::lock_guard<std::recursive_mutex> lock(TagLock());
- if (gDefaultTag == nullptr) {
- gDefaultTag = new std::string(getprogname());
- }
-
- if (liblog_functions) {
- __android_logger_data logger_data = {sizeof(__android_logger_data), LOG_ID_DEFAULT, priority,
- gDefaultTag->c_str(), file, line};
- __android_log_write_logger_data(&logger_data, message);
- } else {
- Logger()(DEFAULT, severity, gDefaultTag->c_str(), file, line, message);
- }
+ if (liblog_functions) {
+ __android_logger_data logger_data = {
+ sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
+ __android_log_write_logger_data(&logger_data, message);
} else {
- if (liblog_functions) {
- __android_logger_data logger_data = {
- sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
- __android_log_write_logger_data(&logger_data, message);
+ if (tag == nullptr) {
+ std::lock_guard<std::recursive_mutex> lock(TagLock());
+ if (gDefaultTag == nullptr) {
+ gDefaultTag = new std::string(getprogname());
+ }
+
+ Logger()(DEFAULT, severity, gDefaultTag->c_str(), file, line, message);
} else {
Logger()(DEFAULT, severity, tag, file, line, message);
}
@@ -613,7 +608,6 @@
// we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
// take into consideration the value from SetMinimumLogSeverity().
if (liblog_functions) {
- // TODO: It is safe to pass nullptr for tag, but it will be better to use the default log tag.
int priority = LogSeverityToPriority(severity);
return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
} else {
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 8f46196..3a453e6 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -603,21 +603,6 @@
LOG(ERROR) << "foobar";
}
-TEST(logging, SetDefaultTag) {
- constexpr const char* expected_tag = "test_tag";
- constexpr const char* expected_msg = "foobar";
- CapturedStderr cap;
- {
- std::string old_default_tag = android::base::GetDefaultTag();
- android::base::SetDefaultTag(expected_tag);
- android::base::ScopedLogSeverity sls(android::base::LogSeverity::INFO);
- LOG(INFO) << expected_msg;
- android::base::SetDefaultTag(old_default_tag);
- }
- ASSERT_NO_FATAL_FAILURE(
- CheckMessage(cap, android::base::LogSeverity::INFO, expected_msg, expected_tag));
-}
-
TEST(logging, StdioLogger) {
CapturedStderr cap_err;
CapturedStdout cap_out;
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ed82066..9180a06 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -86,6 +86,7 @@
#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
#define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
+#define SYSFS_EXT4_CASEFOLD "/sys/fs/ext4/features/casefold"
// FIXME: this should be in system/extras
#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800
@@ -100,6 +101,7 @@
using android::base::unique_fd;
using android::dm::DeviceMapper;
using android::dm::DmDeviceState;
+using android::dm::DmTargetLinear;
// Realistically, this file should be part of the android::fs_mgr namespace;
using namespace android::fs_mgr;
@@ -123,6 +125,7 @@
FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
FS_STAT_ENABLE_VERITY_FAILED = 0x80000,
+ FS_STAT_ENABLE_CASEFOLD_FAILED = 0x100000,
};
static void log_fs_stat(const std::string& blk_device, int fs_stat) {
@@ -344,6 +347,7 @@
const struct ext4_super_block* sb, int* fs_stat) {
bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
bool want_quota = entry.fs_mgr_flags.quota;
+ bool want_projid = android::base::GetBoolProperty("ro.emulated_storage.projid", false);
if (has_quota == want_quota) {
return;
@@ -360,12 +364,16 @@
if (want_quota) {
LINFO << "Enabling quotas on " << blk_device;
argv[1] = "-Oquota";
- argv[2] = "-Qusrquota,grpquota";
+ // Once usr/grp unneeded, make just prjquota to save overhead
+ if (want_projid)
+ argv[2] = "-Qusrquota,grpquota,prjquota";
+ else
+ argv[2] = "-Qusrquota,grpquota";
*fs_stat |= FS_STAT_QUOTA_ENABLED;
} else {
LINFO << "Disabling quotas on " << blk_device;
argv[1] = "-O^quota";
- argv[2] = "-Q^usrquota,^grpquota";
+ argv[2] = "-Q^usrquota,^grpquota,^prjquota";
}
if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
@@ -498,6 +506,42 @@
}
}
+// Enable casefold if needed.
+static void tune_casefold(const std::string& blk_device, const struct ext4_super_block* sb,
+ int* fs_stat) {
+ bool has_casefold =
+ (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_CASEFOLD)) != 0;
+ bool wants_casefold = android::base::GetBoolProperty("ro.emulated_storage.casefold", false);
+
+ if (!wants_casefold || has_casefold) return;
+
+ std::string casefold_support;
+ if (!android::base::ReadFileToString(SYSFS_EXT4_CASEFOLD, &casefold_support)) {
+ LERROR << "Failed to open " << SYSFS_EXT4_CASEFOLD;
+ return;
+ }
+
+ if (!(android::base::Trim(casefold_support) == "supported")) {
+ LERROR << "Current ext4 casefolding not supported by kernel";
+ return;
+ }
+
+ if (!tune2fs_available()) {
+ LERROR << "Unable to enable ext4 casefold on " << blk_device
+ << " because " TUNE2FS_BIN " is missing";
+ return;
+ }
+
+ LINFO << "Enabling ext4 casefold on " << blk_device;
+
+ const char* argv[] = {TUNE2FS_BIN, "-O", "casefold", "-E", "encoding=utf8", blk_device.c_str()};
+ if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
+ LERROR << "Failed to run " TUNE2FS_BIN " to enable "
+ << "ext4 casefold on " << blk_device;
+ *fs_stat |= FS_STAT_ENABLE_CASEFOLD_FAILED;
+ }
+}
+
// Read the primary superblock from an f2fs filesystem. On failure return
// false. If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
#define F2FS_BLKSIZE 4096
@@ -595,6 +639,7 @@
tune_reserved_size(blk_device, entry, &sb, &fs_stat);
tune_encrypt(blk_device, entry, &sb, &fs_stat);
tune_verity(blk_device, entry, &sb, &fs_stat);
+ tune_casefold(blk_device, &sb, &fs_stat);
}
}
@@ -1070,6 +1115,83 @@
}
}
+static constexpr const char* kUserdataWrapperName = "userdata-wrapper";
+
+static void WrapUserdata(FstabEntry* entry, dev_t dev, const std::string& block_device) {
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (dm.GetState(kUserdataWrapperName) != DmDeviceState::INVALID) {
+ // This will report failure for us. If we do fail to get the path,
+ // we leave the device unwrapped.
+ dm.GetDmDevicePathByName(kUserdataWrapperName, &entry->blk_device);
+ return;
+ }
+
+ unique_fd fd(open(block_device.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) {
+ PLOG(ERROR) << "open failed: " << entry->blk_device;
+ return;
+ }
+
+ auto dev_str = android::base::StringPrintf("%u:%u", major(dev), minor(dev));
+ uint64_t sectors = get_block_device_size(fd) / 512;
+
+ android::dm::DmTable table;
+ table.Emplace<DmTargetLinear>(0, sectors, dev_str, 0);
+
+ std::string dm_path;
+ if (!dm.CreateDevice(kUserdataWrapperName, table, &dm_path, 20s)) {
+ LOG(ERROR) << "Failed to create userdata wrapper device";
+ return;
+ }
+ entry->blk_device = dm_path;
+}
+
+// When using Virtual A/B, partitions can be backed by /data and mapped with
+// device-mapper in first-stage init. This can happen when merging an OTA or
+// when using adb remount to house "scratch". In this case, /data cannot be
+// mounted directly off the userdata block device, and e2fsck will refuse to
+// scan it, because the kernel reports the block device as in-use.
+//
+// As a workaround, when mounting /data, we create a trivial dm-linear wrapper
+// if the underlying block device already has dependencies. Note that we make
+// an exception for metadata-encrypted devices, since dm-default-key is already
+// a wrapper.
+static void WrapUserdataIfNeeded(FstabEntry* entry, const std::string& actual_block_device = {}) {
+ const auto& block_device =
+ actual_block_device.empty() ? entry->blk_device : actual_block_device;
+ if (entry->mount_point != "/data" || !entry->key_dir.empty() ||
+ android::base::StartsWith(block_device, "/dev/block/dm-")) {
+ return;
+ }
+
+ struct stat st;
+ if (stat(block_device.c_str(), &st) < 0) {
+ PLOG(ERROR) << "stat failed: " << block_device;
+ return;
+ }
+
+ std::string path = android::base::StringPrintf("/sys/dev/block/%u:%u/holders",
+ major(st.st_rdev), minor(st.st_rdev));
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ PLOG(ERROR) << "opendir failed: " << path;
+ return;
+ }
+
+ struct dirent* d;
+ bool has_holders = false;
+ while ((d = readdir(dir.get())) != nullptr) {
+ if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
+ has_holders = true;
+ break;
+ }
+ }
+
+ if (has_holders) {
+ WrapUserdata(entry, st.st_rdev, block_device);
+ }
+}
+
static bool IsMountPointMounted(const std::string& mount_point) {
// Check if this is already mounted.
Fstab fstab;
@@ -1149,6 +1271,8 @@
}
}
+ WrapUserdataIfNeeded(¤t_entry);
+
if (!checkpoint_manager.Update(¤t_entry)) {
continue;
}
@@ -1419,6 +1543,9 @@
}
std::string block_device;
if (auto entry = GetEntryForMountPoint(&proc_mounts, "/data"); entry != nullptr) {
+ // Note: we don't care about a userdata wrapper here, since it's safe
+ // to remount on top of the bow device instead, there will be no
+ // conflicts.
block_device = entry->blk_device;
} else {
LERROR << "/data is not mounted";
@@ -1537,6 +1664,8 @@
}
}
+ WrapUserdataIfNeeded(&fstab_entry, n_blk_device);
+
if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) {
LERROR << "Could not set up checkpoint partition, skipping!";
continue;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 912087c..88d6b8d 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -828,7 +828,8 @@
cancelled = true;
break;
default:
- LOG(ERROR) << "Unknown merge status: " << static_cast<uint32_t>(snapshot_state);
+ LOG(ERROR) << "Unknown merge status for \"" << snapshot << "\": "
+ << "\"" << snapshot_state << "\"";
failed = true;
break;
}
@@ -1218,7 +1219,8 @@
if (!UnmapPartitionWithSnapshot(lock, name) || !DeleteSnapshot(lock, name)) {
// Remember whether or not we were able to unmap the cow image.
auto cow_image_device = GetCowImageDeviceName(name);
- has_mapped_cow_images |= images_->IsImageMapped(cow_image_device);
+ has_mapped_cow_images |=
+ (EnsureImageManager() && images_->IsImageMapped(cow_image_device));
ok = false;
}
@@ -1706,7 +1708,7 @@
} else if (contents == "merge-failed") {
return UpdateState::MergeFailed;
} else {
- LOG(ERROR) << "Unknown merge state in update state file";
+ LOG(ERROR) << "Unknown merge state in update state file: \"" << contents << "\"";
return UpdateState::None;
}
}
@@ -1728,7 +1730,7 @@
case UpdateState::MergeFailed:
return os << "merge-failed";
default:
- LOG(ERROR) << "Unknown update state";
+ LOG(ERROR) << "Unknown update state: " << static_cast<uint32_t>(state);
return os;
}
}
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 65c59bd..fd9a3eb 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -196,6 +196,7 @@
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
CAP_MASK_LONG(CAP_SETGID),
"system/bin/simpleperf_app_runner" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/e2fsck" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index f9a3df9..ff6b036 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -130,6 +130,7 @@
#define AID_GSID 1074 /* GSI service daemon */
#define AID_FSVERITY_CERT 1075 /* fs-verity key ownership in keystore */
#define AID_CREDSTORE 1076 /* identity credential manager service */
+#define AID_EXTERNAL_STORAGE 1077 /* Full external storage access including USB OTG volumes */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 58c96b6..2e87b5b 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -39,6 +39,7 @@
name: "liblog_headers",
host_supported: true,
vendor_available: true,
+ ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
export_include_dirs: ["include"],
@@ -62,6 +63,7 @@
cc_library {
name: "liblog",
host_supported: true,
+ ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
srcs: liblog_sources,
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 00aafaa..c84ddf7 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -276,6 +276,13 @@
*/
int __android_log_get_minimum_priority();
+/**
+ * Sets the default tag if no tag is provided when writing a log message. Defaults to
+ * getprogname(). This truncates tag to the maximum log message size, though appropriate tags
+ * should be much smaller.
+ */
+void __android_log_set_default_tag(const char* tag);
+
#ifdef __cplusplus
}
#endif
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 62b9805..198cdae 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -73,6 +73,7 @@
__android_log_logd_logger;
__android_log_security_bswrite; # apex
__android_log_set_aborter;
+ __android_log_set_default_tag;
__android_log_set_logger;
__android_log_set_minimum_priority;
__android_log_stderr_logger;
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 1783854..3733357 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -14,8 +14,11 @@
* limitations under the License.
*/
+#include "logger_write.h"
+
#include <errno.h>
#include <inttypes.h>
+#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
@@ -31,6 +34,7 @@
#include <private/android_logger.h>
#include "android/log.h"
+#include "log/log_read.h"
#include "logger.h"
#include "rwlock.h"
#include "uio.h"
@@ -106,6 +110,45 @@
#endif
}
+#if defined(__GLIBC__) || defined(_WIN32)
+static const char* getprogname() {
+#if defined(__GLIBC__)
+ return program_invocation_short_name;
+#elif defined(_WIN32)
+ static bool first = true;
+ static char progname[MAX_PATH] = {};
+
+ if (first) {
+ char path[PATH_MAX + 1];
+ DWORD result = GetModuleFileName(nullptr, path, sizeof(path) - 1);
+ if (result == 0 || result == sizeof(path) - 1) return "";
+ path[PATH_MAX - 1] = 0;
+
+ char* path_basename = basename(path);
+
+ snprintf(progname, sizeof(progname), "%s", path_basename);
+ first = false;
+ }
+
+ return progname;
+#endif
+}
+#endif
+
+// It's possible for logging to happen during static initialization before our globals are
+// initialized, so we place this std::string in a function such that it is initialized on the first
+// call.
+std::string& GetDefaultTag() {
+ static std::string default_tag = getprogname();
+ return default_tag;
+}
+RwLock default_tag_lock;
+
+void __android_log_set_default_tag(const char* tag) {
+ auto lock = std::unique_lock{default_tag_lock};
+ GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
+}
+
static int minimum_log_priority = ANDROID_LOG_DEFAULT;
int __android_log_set_minimum_priority(int priority) {
int old_minimum_log_priority = minimum_log_priority;
@@ -270,7 +313,11 @@
}
void __android_log_write_logger_data(__android_logger_data* logger_data, const char* msg) {
- if (logger_data->tag == nullptr) logger_data->tag = "";
+ auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
+ if (logger_data->tag == nullptr) {
+ tag_lock.lock();
+ logger_data->tag = GetDefaultTag().c_str();
+ }
#if __BIONIC__
if (logger_data->priority == ANDROID_LOG_FATAL) {
diff --git a/liblog/logger_write.h b/liblog/logger_write.h
new file mode 100644
index 0000000..065fd55
--- /dev/null
+++ b/liblog/logger_write.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "rwlock.h"
+
+std::string& GetDefaultTag(); // Must read lock default_tag_lock
+extern RwLock default_tag_lock;
\ No newline at end of file
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index a53c92b..b13662f 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -25,9 +25,12 @@
#include <unistd.h>
#include <algorithm>
+#include <shared_mutex>
#include <private/android_logger.h>
+#include "logger_write.h"
+
static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
static int lock() {
@@ -93,10 +96,17 @@
/* sizeof() is used on this array below */
static const char log_namespace[] = "persist.log.tag.";
static const size_t base_offset = 8; /* skip "persist." */
- /* calculate the size of our key temporary buffer */
- const size_t taglen = tag ? len : 0;
+
+ auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
+ if (tag == nullptr || len == 0) {
+ tag_lock.lock();
+ auto& tag_string = GetDefaultTag();
+ tag = tag_string.c_str();
+ len = tag_string.size();
+ }
+
/* sizeof(log_namespace) = strlen(log_namespace) + 1 */
- char key[sizeof(log_namespace) + taglen];
+ char key[sizeof(log_namespace) + len];
char* kp;
size_t i;
char c = 0;
@@ -146,7 +156,7 @@
}
}
- if (taglen) {
+ if (len) {
int local_change_detected = change_detected;
if (!not_locked) {
if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 3288954..b3364f9 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -54,6 +54,7 @@
],
srcs: [
"libc_test.cpp",
+ "liblog_default_tag.cpp",
"liblog_global_state.cpp",
"liblog_test.cpp",
"log_id_test.cpp",
diff --git a/liblog/tests/liblog_default_tag.cpp b/liblog/tests/liblog_default_tag.cpp
new file mode 100644
index 0000000..5643f63
--- /dev/null
+++ b/liblog/tests/liblog_default_tag.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+// LOG_TAG must be unset for android-base's logging to use a default tag.
+#undef LOG_TAG
+
+#include <stdlib.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/log.h>
+
+#include <gtest/gtest.h>
+
+TEST(liblog_default_tag, no_default_tag_libbase_write_first) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+
+ expected_tag = getprogname();
+ LOG(WARNING) << "message";
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_WARN, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, no_default_tag_liblog_write_first) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+
+ expected_tag = getprogname();
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_WARN, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(WARNING) << "message";
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, libbase_sets_default_tag) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "libbase_test_tag";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+ SetDefaultTag(expected_tag);
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_WARN, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(WARNING) << "message";
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, liblog_sets_default_tag) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "liblog_test_tag";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+ __android_log_set_default_tag(expected_tag.c_str());
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_WARN, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(WARNING) << "message";
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, default_tag_plus_log_severity) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = "liblog_test_tag";
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+ __android_log_set_default_tag(expected_tag.c_str());
+
+ auto log_tag_property = "log.tag." + expected_tag;
+ SetProperty(log_tag_property, "V");
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_VERBOSE, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(VERBOSE) << "message";
+ EXPECT_TRUE(message_seen);
+}
+
+TEST(liblog_default_tag, generated_default_tag_plus_log_severity) {
+ using namespace android::base;
+ bool message_seen = false;
+ std::string expected_tag = getprogname();
+ SetLogger([&](LogId, LogSeverity, const char* tag, const char*, unsigned int, const char*) {
+ message_seen = true;
+ EXPECT_EQ(expected_tag, tag);
+ });
+
+ // Even without any calls to SetDefaultTag(), the first message that attempts to log, will
+ // generate a default tag from getprogname() and check log.tag.<default tag> for loggability. This
+ // case checks that we can log a Verbose message when log.tag.<getprogname()> is set to 'V'.
+ auto log_tag_property = "log.tag." + expected_tag;
+ SetProperty(log_tag_property, "V");
+
+ __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_VERBOSE, nullptr, "message");
+ EXPECT_TRUE(message_seen);
+ message_seen = false;
+
+ LOG(VERBOSE) << "message";
+ EXPECT_TRUE(message_seen);
+}
\ No newline at end of file
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 8212eba..5999e39 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -257,8 +257,8 @@
*
* Returns zero on success and negative errno on failure.
*/
-int ifc_act_on_address(int action, const char *name, const char *address,
- int prefixlen) {
+int ifc_act_on_address(int action, const char* name, const char* address, int prefixlen,
+ bool nodad) {
int ifindex, s, len, ret;
struct sockaddr_storage ss;
int saved_errno;
@@ -311,6 +311,7 @@
// Interface address message header.
req.r.ifa_family = ss.ss_family;
+ req.r.ifa_flags = nodad ? IFA_F_NODAD : 0;
req.r.ifa_prefixlen = prefixlen;
req.r.ifa_index = ifindex;
@@ -363,12 +364,12 @@
// Returns zero on success and negative errno on failure.
int ifc_add_address(const char *name, const char *address, int prefixlen) {
- return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
+ return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, /*nodad*/ false);
}
// Returns zero on success and negative errno on failure.
int ifc_del_address(const char *name, const char * address, int prefixlen) {
- return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
+ return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, /*nodad*/ false);
}
/*
diff --git a/libnetutils/include/netutils/ifc.h b/libnetutils/include/netutils/ifc.h
index 3b27234..ee896ac 100644
--- a/libnetutils/include/netutils/ifc.h
+++ b/libnetutils/include/netutils/ifc.h
@@ -17,8 +17,9 @@
#ifndef _NETUTILS_IFC_H_
#define _NETUTILS_IFC_H_
-#include <sys/cdefs.h>
#include <arpa/inet.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -42,6 +43,8 @@
extern int ifc_get_addr(const char *name, in_addr_t *addr);
extern int ifc_set_addr(const char *name, in_addr_t addr);
+extern int ifc_act_on_address(int action, const char* name, const char* address, int prefixlen,
+ bool nodad);
extern int ifc_add_address(const char *name, const char *address,
int prefixlen);
extern int ifc_del_address(const char *name, const char *address,
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 16339d3..698e74d 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -138,8 +138,17 @@
return enabled;
}
+static bool schedtune_enabled() {
+ return (CgroupMap::GetInstance().FindController("schedtune").IsUsable());
+}
+
+static bool cpuctl_enabled() {
+ return (CgroupMap::GetInstance().FindController("cpu").IsUsable());
+}
+
bool schedboost_enabled() {
- static bool enabled = (CgroupMap::GetInstance().FindController("schedtune").IsUsable());
+ static bool enabled = schedtune_enabled() || cpuctl_enabled();
+
return enabled;
}
@@ -162,7 +171,9 @@
std::string group;
if (schedboost_enabled()) {
- if (getCGroupSubsys(tid, "schedtune", group) < 0) return -1;
+ if ((getCGroupSubsys(tid, "schedtune", group) < 0) &&
+ (getCGroupSubsys(tid, "cpu", group) < 0))
+ return -1;
}
if (group.empty() && cpusets_enabled()) {
if (getCGroupSubsys(tid, "cpuset", group) < 0) return -1;
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 9447f86..72f01af 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -288,6 +288,11 @@
return true;
}
+void TaskProfile::MoveTo(TaskProfile* profile) {
+ profile->elements_ = std::move(elements_);
+ profile->res_cached_ = res_cached_;
+}
+
bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
for (const auto& element : elements_) {
if (!element->ExecuteForProcess(uid, pid)) {
@@ -458,7 +463,15 @@
LOG(WARNING) << "Unknown profile action: " << action_name;
}
}
- profiles_[profile_name] = profile;
+ auto iter = profiles_.find(profile_name);
+ if (iter == profiles_.end()) {
+ profiles_[profile_name] = profile;
+ } else {
+ // Move the content rather that replace the profile because old profile might be
+ // referenced from an aggregate profile if vendor overrides task profiles
+ profile->MoveTo(iter->second.get());
+ profile.reset();
+ }
}
const Json::Value& aggregateprofiles_val = root["AggregateProfiles"];
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 9f2308c..a64ca50 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -143,6 +143,7 @@
TaskProfile() : res_cached_(false) {}
void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); }
+ void MoveTo(TaskProfile* profile);
bool ExecuteForProcess(uid_t uid, pid_t pid) const;
bool ExecuteForTask(int tid) const;
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 88146e9..135904b 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -3,6 +3,7 @@
cc_library {
name: "libsparse",
host_supported: true,
+ ramdisk_available: true,
recovery_available: true,
unique_host_soname: true,
srcs: [
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 1df1dff..00b3367 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -100,8 +100,8 @@
fn("x27", regs_[ARM64_REG_R27]);
fn("x28", regs_[ARM64_REG_R28]);
fn("x29", regs_[ARM64_REG_R29]);
- fn("sp", regs_[ARM64_REG_SP]);
fn("lr", regs_[ARM64_REG_LR]);
+ fn("sp", regs_[ARM64_REG_SP]);
fn("pc", regs_[ARM64_REG_PC]);
fn("pst", regs_[ARM64_REG_PSTATE]);
}
@@ -110,10 +110,10 @@
arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
+ memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R30 + 1) * sizeof(uint64_t));
uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
- reg_data[ARM64_REG_PC] = user->pc;
reg_data[ARM64_REG_SP] = user->sp;
+ reg_data[ARM64_REG_PC] = user->pc;
reg_data[ARM64_REG_PSTATE] = user->pstate;
return regs;
}
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
index bc95851..47e605a 100644
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -111,8 +111,8 @@
result.push_back({"x27", ARM64_REG_R27});
result.push_back({"x28", ARM64_REG_R28});
result.push_back({"x29", ARM64_REG_R29});
- result.push_back({"sp", ARM64_REG_SP});
result.push_back({"lr", ARM64_REG_LR});
+ result.push_back({"sp", ARM64_REG_SP});
result.push_back({"pc", ARM64_REG_PC});
result.push_back({"pst", ARM64_REG_PSTATE});
return result;
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 7b18438..08e3d22 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -110,7 +110,7 @@
#endif
static int openLogFile(const char* pathname, size_t sizeKB) {
- int fd = open(pathname, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ int fd = open(pathname, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
return fd;
}
diff --git a/logcat/logcatd b/logcat/logcatd
index 622e567..5a1415d 100755
--- a/logcat/logcatd
+++ b/logcat/logcatd
@@ -4,6 +4,10 @@
# first reads the 'last' logcat to persistent storage with `-L` then run logcat again without
# `-L` to read the current logcat buffers to persistent storage.
+# init sets the umask to 077 for forked processes. logpersist needs to create files that are group
+# readable. So relax the umask to only disallow group wx and world rwx.
+umask 037
+
has_last="false"
for arg in "$@"; do
if [ "$arg" == "-L" -o "$arg" == "--last" ]; then
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index e986184..64d5500 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -30,8 +30,8 @@
setprop logd.logpersistd.enable true
on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd
- # all exec/services are called with umask(077), so no gain beyond 0700
- mkdir /data/misc/logd 0700 logd log
+ # log group should be able to read persisted logs
+ mkdir /data/misc/logd 0750 logd log
start logcatd
# stop logcatd service and clear data
diff --git a/logd/logtagd.rc b/logd/logtagd.rc
index 46aa8c1..248a78c 100644
--- a/logd/logtagd.rc
+++ b/logd/logtagd.rc
@@ -2,7 +2,7 @@
# logtagd event log tag service (debug only)
#
on post-fs-data
- mkdir /data/misc/logd 0700 logd log
+ mkdir /data/misc/logd 0750 logd log
write /data/misc/logd/event-log-tags ""
chown logd log /data/misc/logd/event-log-tags
chmod 0600 /data/misc/logd/event-log-tags
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index ac802b5..108d15a 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -2,6 +2,7 @@
name: "libpropertyinfoparser",
host_supported: true,
vendor_available: true,
+ ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
srcs: ["property_info_parser.cpp"],
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e575808..7d27c3a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -165,7 +165,7 @@
mkdir /mnt/secure/asec 0700 root root
mkdir /mnt/asec 0755 root system
mkdir /mnt/obb 0755 root system
- mkdir /mnt/media_rw 0750 root media_rw
+ mkdir /mnt/media_rw 0750 root external_storage
mkdir /mnt/user 0755 root root
mkdir /mnt/user/0 0755 root root
mkdir /mnt/user/0/self 0755 root root