Merge "init: handle sys.powerctl immediately"
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 7da94ce..7a87df4 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -32,10 +32,10 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <libminijail.h>
+#include <log/log_properties.h>
#include <scoped_minijail.h>
#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
#include "debuggerd/handler.h"
#include "selinux/android.h"
diff --git a/adb/services.cpp b/adb/services.cpp
index f764c52..4327044 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -43,7 +43,7 @@
#include <android-base/properties.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
-#include <private/android_logger.h>
+#include <log/log_properties.h>
#endif
#include "adb.h"
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index 76b156d..d4dd256 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -26,7 +26,7 @@
#include "android-base/properties.h"
#include "android-base/stringprintf.h"
-#include <private/android_logger.h>
+#include <log/log_properties.h>
#include "adb.h"
#include "adb_io.h"
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index c05903f..59a48f5 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -32,7 +32,7 @@
#if !ADB_HOST
#include <android-base/properties.h>
-#include <private/android_logger.h>
+#include <log/log_properties.h>
#endif
#include "adb.h"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e635e53..4ddcc52 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -48,8 +48,8 @@
#include <linux/fs.h>
#include <linux/loop.h>
#include <linux/magic.h>
+#include <log/log_properties.h>
#include <logwrap/logwrap.h>
-#include <private/android_logger.h> // for __android_log_is_debuggable()
#include "fs_mgr.h"
#include "fs_mgr_avb.h"
diff --git a/init/devices.cpp b/init/devices.cpp
index ad313a0..6e13863 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "devices.h"
+
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -27,23 +29,19 @@
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/time.h>
-#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <algorithm>
#include <memory>
-#include <string>
#include <thread>
-#include <vector>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <cutils/list.h>
#include <cutils/uevent.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
@@ -51,119 +49,67 @@
#include <selinux/label.h>
#include <selinux/selinux.h>
-#include "devices.h"
#include "ueventd_parser.h"
#include "util.h"
-#define SYSFS_PREFIX "/sys"
-
extern struct selabel_handle *sehandle;
static android::base::unique_fd device_fd;
-struct perms_ {
- char *name;
- char *attr;
- mode_t perm;
- unsigned int uid;
- unsigned int gid;
- unsigned short prefix;
- unsigned short wildcard;
-};
-
-struct perm_node {
- struct perms_ dp;
- struct listnode plist;
-};
-
-static list_declare(sys_perms);
-static list_declare(dev_perms);
-
-int add_dev_perms(const char *name, const char *attr,
- mode_t perm, unsigned int uid, unsigned int gid,
- unsigned short prefix,
- unsigned short wildcard) {
- struct perm_node *node = (perm_node*) calloc(1, sizeof(*node));
- if (!node)
- return -ENOMEM;
-
- node->dp.name = strdup(name);
- if (!node->dp.name) {
- free(node);
- return -ENOMEM;
+Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid)
+ : name_(name), perm_(perm), uid_(uid), gid_(gid), prefix_(false), wildcard_(false) {
+ // If the first * is the last character, then we'll treat name_ as a prefix
+ // Otherwise, if a * is present, then we do a full fnmatch().
+ auto wildcard_position = name_.find('*');
+ if (wildcard_position == name_.length() - 1) {
+ prefix_ = true;
+ name_.pop_back();
+ } else if (wildcard_position != std::string::npos) {
+ wildcard_ = true;
}
-
- if (attr) {
- node->dp.attr = strdup(attr);
- if (!node->dp.attr) {
- free(node->dp.name);
- free(node);
- return -ENOMEM;
- }
- }
-
- node->dp.perm = perm;
- node->dp.uid = uid;
- node->dp.gid = gid;
- node->dp.prefix = prefix;
- node->dp.wildcard = wildcard;
-
- if (attr)
- list_add_tail(&sys_perms, &node->plist);
- else
- list_add_tail(&dev_perms, &node->plist);
-
- return 0;
}
-static bool perm_path_matches(const char *path, struct perms_ *dp)
-{
- if (dp->prefix) {
- if (strncmp(path, dp->name, strlen(dp->name)) == 0)
- return true;
- } else if (dp->wildcard) {
- if (fnmatch(dp->name, path, FNM_PATHNAME) == 0)
- return true;
+bool Permissions::Match(const std::string& path) const {
+ if (prefix_) {
+ return android::base::StartsWith(path, name_.c_str());
+ } else if (wildcard_) {
+ return fnmatch(name_.c_str(), path.c_str(), FNM_PATHNAME) == 0;
} else {
- if (strcmp(path, dp->name) == 0)
- return true;
+ return path == name_;
}
return false;
}
-static bool match_subsystem(perms_* dp, const char* pattern,
- const char* path, const char* subsystem) {
- if (!pattern || !subsystem || strstr(dp->name, subsystem) == NULL) {
- return false;
+bool SysfsPermissions::MatchWithSubsystem(const std::string& path,
+ const std::string& subsystem) const {
+ std::string path_basename = android::base::Basename(path);
+ if (name().find(subsystem) != std::string::npos) {
+ if (Match("/sys/class/" + subsystem + "/" + path_basename)) return true;
+ if (Match("/sys/bus/" + subsystem + "/devices/" + path_basename)) return true;
}
-
- std::string subsys_path = android::base::StringPrintf(pattern, subsystem, basename(path));
- return perm_path_matches(subsys_path.c_str(), dp);
+ return Match(path);
}
-static void fixup_sys_perms(const std::string& upath, const std::string& subsystem) {
+void SysfsPermissions::SetPermissions(const std::string& path) const {
+ std::string attribute_file = path + "/" + attribute_;
+ LOG(INFO) << "fixup " << attribute_file << " " << uid() << " " << gid() << " " << std::oct
+ << perm();
+ chown(attribute_file.c_str(), uid(), gid());
+ chmod(attribute_file.c_str(), perm());
+}
+
+// TODO: Move these to be member variables of a future devices class.
+std::vector<Permissions> dev_permissions;
+std::vector<SysfsPermissions> sysfs_permissions;
+
+static void fixup_sys_permissions(const std::string& upath, const std::string& subsystem) {
// upaths omit the "/sys" that paths in this list
// contain, so we prepend it...
- std::string path = SYSFS_PREFIX + upath;
+ std::string path = "/sys" + upath;
- listnode* node;
- list_for_each(node, &sys_perms) {
- perms_* dp = &(node_to_item(node, perm_node, plist))->dp;
- if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem.c_str())) {
- ; // matched
- } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(),
- subsystem.c_str())) {
- ; // matched
- } else if (!perm_path_matches(path.c_str(), dp)) {
- continue;
- }
-
- std::string attr_file = path + "/" + dp->attr;
- LOG(INFO) << "fixup " << attr_file
- << " " << dp->uid << " " << dp->gid << " " << std::oct << dp->perm;
- chown(attr_file.c_str(), dp->uid, dp->gid);
- chmod(attr_file.c_str(), dp->perm);
+ for (const auto& s : sysfs_permissions) {
+ if (s.MatchWithSubsystem(path, subsystem)) s.SetPermissions(path);
}
if (access(path.c_str(), F_OK) == 0) {
@@ -172,42 +118,26 @@
}
}
-static mode_t get_device_perm(const char* path, const std::vector<std::string>& links,
- unsigned* uid, unsigned* gid) {
- struct listnode *node;
- struct perm_node *perm_node;
- struct perms_ *dp;
-
- /* search the perms list in reverse so that ueventd.$hardware can
- * override ueventd.rc
- */
- list_for_each_reverse(node, &dev_perms) {
- perm_node = node_to_item(node, struct perm_node, plist);
- dp = &perm_node->dp;
-
- if (perm_path_matches(path, dp) ||
- std::any_of(links.begin(), links.end(),
- [dp](const auto& link) { return perm_path_matches(link.c_str(), dp); })) {
- *uid = dp->uid;
- *gid = dp->gid;
- return dp->perm;
+static std::tuple<mode_t, uid_t, gid_t> get_device_permissions(
+ const std::string& path, const std::vector<std::string>& links) {
+ // Search the perms list in reverse so that ueventd.$hardware can override ueventd.rc.
+ for (auto it = dev_permissions.rbegin(); it != dev_permissions.rend(); ++it) {
+ if (it->Match(path) || std::any_of(links.begin(), links.end(),
+ [it](const auto& link) { return it->Match(link); })) {
+ return {it->perm(), it->uid(), it->gid()};
}
}
/* Default if nothing found. */
- *uid = 0;
- *gid = 0;
- return 0600;
+ return {0600, 0, 0};
}
static void make_device(const std::string& path, int block, int major, int minor,
const std::vector<std::string>& links) {
- unsigned uid;
- unsigned gid;
- mode_t mode;
dev_t dev;
char *secontext = NULL;
- mode = get_device_perm(path.c_str(), links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
+ auto [mode, uid, gid] = get_device_permissions(path, links);
+ mode |= (block ? S_IFBLK : S_IFCHR);
if (sehandle) {
std::vector<const char*> c_links;
@@ -607,7 +537,7 @@
static void handle_device_event(struct uevent *uevent)
{
if (uevent->action == "add" || uevent->action == "change" || uevent->action == "online") {
- fixup_sys_perms(uevent->path, uevent->subsystem);
+ fixup_sys_permissions(uevent->path, uevent->subsystem);
}
if (uevent->subsystem == "block") {
diff --git a/init/devices.h b/init/devices.h
index b8b039f..2cbae66 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -18,6 +18,7 @@
#define _INIT_DEVICES_H
#include <sys/stat.h>
+#include <sys/types.h>
#include <functional>
#include <string>
@@ -47,15 +48,48 @@
int minor;
};
+class Permissions {
+ public:
+ Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid);
+
+ bool Match(const std::string& path) const;
+
+ mode_t perm() const { return perm_; }
+ uid_t uid() const { return uid_; }
+ gid_t gid() const { return gid_; }
+
+ protected:
+ const std::string& name() const { return name_; }
+
+ private:
+ std::string name_;
+ mode_t perm_;
+ uid_t uid_;
+ gid_t gid_;
+ bool prefix_;
+ bool wildcard_;
+};
+
+class SysfsPermissions : public Permissions {
+ public:
+ SysfsPermissions(const std::string& name, const std::string& attribute, mode_t perm, uid_t uid,
+ gid_t gid)
+ : Permissions(name, perm, uid, gid), attribute_(attribute) {}
+
+ bool MatchWithSubsystem(const std::string& path, const std::string& subsystem) const;
+ void SetPermissions(const std::string& path) const;
+
+ private:
+ const std::string attribute_;
+};
+
+extern std::vector<Permissions> dev_permissions;
+extern std::vector<SysfsPermissions> sysfs_permissions;
+
typedef std::function<coldboot_action_t(struct uevent* uevent)> coldboot_callback;
extern coldboot_action_t handle_device_fd(coldboot_callback fn = nullptr);
extern void device_init(const char* path = nullptr, coldboot_callback fn = nullptr);
extern void device_close();
-
-extern int add_dev_perms(const char *name, const char *attr,
- mode_t perm, unsigned int uid,
- unsigned int gid, unsigned short prefix,
- unsigned short wildcard);
int get_device_fd();
// Exposed for testing
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index 693fb54..66521db 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -316,3 +316,94 @@
sanitize_partition_name(&string);
EXPECT_EQ("_", string);
}
+
+TEST(devices, DevPermissionsMatchNormal) {
+ // Basic from ueventd.rc
+ // /dev/null 0666 root root
+ Permissions permissions("/dev/null", 0666, 0, 0);
+ EXPECT_TRUE(permissions.Match("/dev/null"));
+ EXPECT_FALSE(permissions.Match("/dev/nullsuffix"));
+ EXPECT_FALSE(permissions.Match("/dev/nul"));
+ EXPECT_EQ(0666U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(0U, permissions.gid());
+}
+
+TEST(devices, DevPermissionsMatchPrefix) {
+ // Prefix from ueventd.rc
+ // /dev/dri/* 0666 root graphics
+ Permissions permissions("/dev/dri/*", 0666, 0, 1000);
+ EXPECT_TRUE(permissions.Match("/dev/dri/some_dri_device"));
+ EXPECT_TRUE(permissions.Match("/dev/dri/some_other_dri_device"));
+ EXPECT_TRUE(permissions.Match("/dev/dri/"));
+ EXPECT_FALSE(permissions.Match("/dev/dr/non_match"));
+ EXPECT_EQ(0666U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1000U, permissions.gid());
+}
+
+TEST(devices, DevPermissionsMatchWildcard) {
+ // Wildcard example
+ // /dev/device*name 0666 root graphics
+ Permissions permissions("/dev/device*name", 0666, 0, 1000);
+ EXPECT_TRUE(permissions.Match("/dev/devicename"));
+ EXPECT_TRUE(permissions.Match("/dev/device123name"));
+ EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
+ EXPECT_FALSE(permissions.Match("/dev/device123name/subdevice"));
+ EXPECT_FALSE(permissions.Match("/dev/deviceame"));
+ EXPECT_EQ(0666U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1000U, permissions.gid());
+}
+
+TEST(devices, DevPermissionsMatchWildcardPrefix) {
+ // Wildcard+Prefix example
+ // /dev/device*name* 0666 root graphics
+ Permissions permissions("/dev/device*name*", 0666, 0, 1000);
+ EXPECT_TRUE(permissions.Match("/dev/devicename"));
+ EXPECT_TRUE(permissions.Match("/dev/device123name"));
+ EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
+ EXPECT_TRUE(permissions.Match("/dev/device123namesomething"));
+ // FNM_PATHNAME doesn't match '/' with *
+ EXPECT_FALSE(permissions.Match("/dev/device123name/something"));
+ EXPECT_FALSE(permissions.Match("/dev/deviceame"));
+ EXPECT_EQ(0666U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1000U, permissions.gid());
+}
+
+TEST(devices, SysfsPermissionsMatchWithSubsystemNormal) {
+ // /sys/devices/virtual/input/input* enable 0660 root input
+ SysfsPermissions permissions("/sys/devices/virtual/input/input*", "enable", 0660, 0, 1001);
+ EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/input0", "input"));
+ EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/not_input0", "input"));
+ EXPECT_EQ(0660U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1001U, permissions.gid());
+}
+
+TEST(devices, SysfsPermissionsMatchWithSubsystemClass) {
+ // /sys/class/input/event* enable 0660 root input
+ SysfsPermissions permissions("/sys/class/input/event*", "enable", 0660, 0, 1001);
+ EXPECT_TRUE(permissions.MatchWithSubsystem(
+ "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "input"));
+ EXPECT_FALSE(permissions.MatchWithSubsystem(
+ "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/not_event0", "input"));
+ EXPECT_FALSE(permissions.MatchWithSubsystem(
+ "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "not_input"));
+ EXPECT_EQ(0660U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1001U, permissions.gid());
+}
+
+TEST(devices, SysfsPermissionsMatchWithSubsystemBus) {
+ // /sys/bus/i2c/devices/i2c-* enable 0660 root input
+ SysfsPermissions permissions("/sys/bus/i2c/devices/i2c-*", "enable", 0660, 0, 1001);
+ EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "i2c"));
+ EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/not-i2c", "i2c"));
+ EXPECT_FALSE(
+ permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "not_i2c"));
+ EXPECT_EQ(0660U, permissions.perm());
+ EXPECT_EQ(0U, permissions.uid());
+ EXPECT_EQ(1001U, permissions.gid());
+}
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index ea767a8..b6c6a01 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -101,8 +101,6 @@
mode_t perm;
uid_t uid;
gid_t gid;
- int prefix = 0;
- int wildcard = 0;
char *endptr;
if (nargs == 0)
@@ -125,15 +123,6 @@
return;
}
- int len = strlen(name);
- char *wildcard_chr = strchr(name, '*');
- if ((name[len - 1] == '*') && (wildcard_chr == (name + len - 1))) {
- prefix = 1;
- name[len - 1] = '\0';
- } else if (wildcard_chr) {
- wildcard = 1;
- }
-
perm = strtol(args[1], &endptr, 8);
if (!endptr || *endptr != '\0') {
LOG(ERROR) << "invalid mode (" << fn << ":" << line << ") '" << args[1] << "'";
@@ -154,13 +143,9 @@
}
gid = grp->gr_gid;
- if (add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard) != 0) {
- PLOG(ERROR) << "add_dev_perms(name=" << name <<
- ", attr=" << attr <<
- ", perm=" << std::oct << perm << std::dec <<
- ", uid=" << uid << ", gid=" << gid <<
- ", prefix=" << prefix << ", wildcard=" << wildcard <<
- ")";
- return;
+ if (attr) {
+ sysfs_permissions.emplace_back(name, attr, perm, uid, gid);
+ } else {
+ dev_permissions.emplace_back(name, perm, uid, gid);
}
}
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index bb82f4d..0a3bab7 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -143,7 +143,10 @@
},
shared_libs: ["liblog"],
- header_libs: ["libcutils_headers"],
+ header_libs: [
+ "libcutils_headers",
+ "libutils_headers",
+ ],
export_header_lib_headers: ["libcutils_headers"],
cflags: [
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index a9c061e..4a0b035 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -28,6 +28,13 @@
#define UNUSED __attribute__((__unused__))
+#ifndef SLOGE
+#define SLOGE ALOGE
+#endif
+#ifndef SLOGW
+#define SLOGW ALOGW
+#endif
+
/* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
* Call this any place a SchedPolicy is used as an input parameter.
* Returns the possibly re-mapped policy.
diff --git a/libcutils/trace-dev.c b/libcutils/trace-dev.c
index 113f423..d45e5a9 100644
--- a/libcutils/trace-dev.c
+++ b/libcutils/trace-dev.c
@@ -29,7 +29,8 @@
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <cutils/trace.h>
-#include <private/android_logger.h>
+#include <log/log.h>
+#include <log/log_properties.h>
/**
* Maximum size of a message that can be logged to the trace buffer.
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 73ed16f..5fc7e35 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -31,6 +31,7 @@
#include <unordered_map>
#include <log/event_tag_map.h>
+#include <log/log_properties.h>
#include <private/android_logger.h>
#include <utils/FastStrcmp.h>
#include <utils/RWLock.h>
diff --git a/liblog/include/log/log_properties.h b/liblog/include/log/log_properties.h
new file mode 100644
index 0000000..7d398a6
--- /dev/null
+++ b/liblog/include/log/log_properties.h
@@ -0,0 +1,35 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** This file is dual licensed. It may be redistributed and/or modified
+** under the terms of the Apache 2.0 License OR version 2 of the GNU
+** General Public License.
+*/
+
+#ifndef _LIBS_LOG_PROPERTIES_H
+#define _LIBS_LOG_PROPERTIES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
+#ifndef __ANDROID_API__
+#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
+#elif __ANDROID_API__ > 24 /* > Nougat */
+#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
+#else
+#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 0
+#endif
+#endif
+
+#if __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
+int __android_log_is_debuggable();
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_LOG_PROPERTIES_H */
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 5f70f7d..9ece0b3 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -41,13 +41,12 @@
static const uint32_t tv_sec_max = 0xFFFFFFFFUL;
static const uint32_t tv_nsec_max = 999999999UL;
- log_time(const timespec& T) {
- tv_sec = static_cast<uint32_t>(T.tv_sec);
- tv_nsec = static_cast<uint32_t>(T.tv_nsec);
+ log_time(const timespec& T)
+ : tv_sec(static_cast<uint32_t>(T.tv_sec)),
+ tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {
}
- log_time(uint32_t sec, uint32_t nsec) {
- tv_sec = sec;
- tv_nsec = nsec;
+ explicit log_time(uint32_t sec, uint32_t nsec = 0)
+ : tv_sec(sec), tv_nsec(nsec) {
}
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
#define __struct_log_time_private_defined
@@ -56,14 +55,14 @@
log_time() {
}
#ifdef __linux__
- log_time(clockid_t id) {
+ explicit log_time(clockid_t id) {
timespec T;
clock_gettime(id, &T);
tv_sec = static_cast<uint32_t>(T.tv_sec);
tv_nsec = static_cast<uint32_t>(T.tv_nsec);
}
#endif
- log_time(const char* T) {
+ explicit log_time(const char* T) {
const uint8_t* c = reinterpret_cast<const uint8_t*>(T);
tv_sec = c[0] | (static_cast<uint32_t>(c[1]) << 8) |
(static_cast<uint32_t>(c[2]) << 16) |
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index e3ccfcf..965de37 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -135,8 +135,6 @@
int __android_log_security_bswrite(int32_t tag, const char* payload);
int __android_log_security(); /* Device Owner is present */
-int __android_log_is_debuggable();
-
#define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1
#define BOOL_DEFAULT_FALSE 0x0 /* false if property not present */
#define BOOL_DEFAULT_TRUE 0x1 /* true if property not present */
diff --git a/liblog/include_vndk/log/log_properties.h b/liblog/include_vndk/log/log_properties.h
new file mode 120000
index 0000000..bbec426
--- /dev/null
+++ b/liblog/include_vndk/log/log_properties.h
@@ -0,0 +1 @@
+../../include/log/log_properties.h
\ No newline at end of file
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index c00f2a0..58fb148 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -39,4 +39,5 @@
LIBLOG_O {
global:
__android_log_is_loggable_len;
+ __android_log_is_debuggable; # vndk
};
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index e71c176..dc42856 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <time.h>
+#include <log/log_properties.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
diff --git a/liblog/properties.c b/liblog/properties.c
index adf1900..c71cbcf 100644
--- a/liblog/properties.c
+++ b/liblog/properties.c
@@ -277,7 +277,7 @@
return logLevel >= 0 && prio >= logLevel;
}
-LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() {
+LIBLOG_ABI_PUBLIC int __android_log_is_debuggable() {
static uint32_t serial;
static struct cache_char tag_cache;
static const char key[] = "ro.debuggable";
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 0c7019a..a6bea0c 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -43,6 +43,8 @@
// Default
#define log_buffer_size(id) mMaxSize[id]
+const log_time LogBuffer::pruneMargin(3, 0);
+
void LogBuffer::init() {
log_id_for_each(i) {
mLastSet[i] = false;
@@ -672,6 +674,8 @@
}
times++;
}
+ log_time watermark(log_time::tv_sec_max, log_time::tv_nsec_max);
+ if (oldest) watermark = oldest->mStart - pruneMargin;
LogBufferElementCollection::iterator it;
@@ -693,7 +697,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && (watermark <= element->getRealTime())) {
busy = true;
if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
oldest->triggerReader_Locked();
@@ -785,7 +789,7 @@
while (it != mLogElements.end()) {
LogBufferElement* element = *it;
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && (watermark <= element->getRealTime())) {
busy = true;
if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
oldest->triggerReader_Locked();
@@ -939,7 +943,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && (watermark <= element->getRealTime())) {
busy = true;
if (whitelist) {
break;
@@ -983,7 +987,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && (watermark <= element->getRealTime())) {
busy = true;
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
// kick a misbehaving log reader client off the island
@@ -1090,13 +1094,15 @@
// client wants to start from the beginning
it = mLogElements.begin();
} else {
- LogBufferElementCollection::iterator last;
// 3 second limit to continue search for out-of-order entries.
- log_time min = start - log_time(3, 0);
+ log_time min = start - pruneMargin;
+
// Cap to 300 iterations we look back for out-of-order entries.
size_t count = 300;
+
// Client wants to start from some specified time. Chances are
// we are better off starting from the end of the time sorted list.
+ LogBufferElementCollection::iterator last;
for (last = it = mLogElements.end(); it != mLogElements.begin();
/* do nothing */) {
--it;
@@ -1112,9 +1118,22 @@
log_time max = start;
+ LogBufferElement* lastElement = nullptr; // iterator corruption paranoia
+ static const size_t maxSkip = 4194304; // maximum entries to skip
+ size_t skip = maxSkip;
for (; it != mLogElements.end(); ++it) {
LogBufferElement* element = *it;
+ if (!--skip) {
+ android::prdebug("reader.per: too many elements skipped");
+ break;
+ }
+ if (element == lastElement) {
+ android::prdebug("reader.per: identical elements");
+ break;
+ }
+ lastElement = element;
+
if (!privileged && (element->getUid() != uid)) {
continue;
}
@@ -1159,6 +1178,7 @@
return max;
}
+ skip = maxSkip;
pthread_mutex_lock(&mLogElementsLock);
}
pthread_mutex_unlock(&mLogElementsLock);
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 19d11cb..1272c20 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -174,6 +174,7 @@
private:
static constexpr size_t minPrune = 4;
static constexpr size_t maxPrune = 256;
+ static const log_time pruneMargin;
void maybePrune(log_id_t id);
bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 67649b1..fcd45bd 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -32,8 +32,8 @@
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <log/log_event_list.h>
+#include <log/log_properties.h>
#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
#include "LogTags.h"
#include "LogUtils.h"
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 88cb67a..a1d154a 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -670,8 +670,12 @@
while (--i) {
int fd = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_SEQPACKET);
- EXPECT_LT(0, fd);
- if (fd < 0) _exit(fd);
+ int save_errno = errno;
+ if (fd < 0) {
+ fprintf(stderr, "failed to open /dev/socket/logdr %s\n",
+ strerror(save_errno));
+ _exit(fd);
+ }
std::string ask = android::base::StringPrintf(
"dumpAndClose lids=0,1,2,3,4,5 timeout=6 start=%" PRIu32
@@ -723,8 +727,12 @@
// active _or_ inactive during the test.
if (content_timeout) {
log_time msg(msg_timeout.entry.sec, msg_timeout.entry.nsec);
- EXPECT_FALSE(msg < now);
- if (msg < now) _exit(-1);
+ if (msg < now) {
+ fprintf(stderr, "%u.%09u < %u.%09u\n", msg_timeout.entry.sec,
+ msg_timeout.entry.nsec, (unsigned)now.tv_sec,
+ (unsigned)now.tv_nsec);
+ _exit(-1);
+ }
if (msg > now) {
now = msg;
now.tv_sec += 30;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8b9b19d..56e736e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -157,25 +157,25 @@
# this ensures that the cpusets are present and usable, but the device's
# init.rc must actually set the correct cpus
mkdir /dev/cpuset/foreground
- write /dev/cpuset/foreground/cpus 0
- write /dev/cpuset/foreground/mems 0
+ copy /dev/cpuset/cpus /dev/cpuset/foreground/cpus
+ copy /dev/cpuset/mems /dev/cpuset/foreground/mems
mkdir /dev/cpuset/foreground/boost
- write /dev/cpuset/foreground/boost/cpus 0
- write /dev/cpuset/foreground/boost/mems 0
+ copy /dev/cpuset/cpus /dev/cpuset/foreground/boost/cpus
+ copy /dev/cpuset/mems /dev/cpuset/foreground/boost/mems
mkdir /dev/cpuset/background
- write /dev/cpuset/background/cpus 0
- write /dev/cpuset/background/mems 0
+ copy /dev/cpuset/cpus /dev/cpuset/background/cpus
+ copy /dev/cpuset/mems /dev/cpuset/background/mems
# system-background is for system tasks that should only run on
# little cores, not on bigs
# to be used only by init, so don't change system-bg permissions
mkdir /dev/cpuset/system-background
- write /dev/cpuset/system-background/cpus 0
- write /dev/cpuset/system-background/mems 0
+ copy /dev/cpuset/cpus /dev/cpuset/system-background/cpus
+ copy /dev/cpuset/mems /dev/cpuset/system-background/mems
mkdir /dev/cpuset/top-app
- write /dev/cpuset/top-app/cpus 0
- write /dev/cpuset/top-app/mems 0
+ copy /dev/cpuset/cpus /dev/cpuset/top-app/cpus
+ copy /dev/cpuset/mems /dev/cpuset/top-app/mems
# change permissions for all cpusets we'll touch at runtime
chown system system /dev/cpuset