Merge "Add dataspace to match upstream EGL extension"
diff --git a/adf/libadfhwc/adfhwc.cpp b/adf/libadfhwc/adfhwc.cpp
index a97862a..63c0f75 100644
--- a/adf/libadfhwc/adfhwc.cpp
+++ b/adf/libadfhwc/adfhwc.cpp
@@ -166,6 +166,71 @@
return 0;
}
+static int32_t adf_display_attribute_hwc2(const adf_interface_data &data,
+ const drm_mode_modeinfo &mode, const uint32_t attribute)
+{
+ switch (attribute) {
+ case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+ if (mode.vrefresh)
+ return 1000000000 / mode.vrefresh;
+ return 0;
+
+ case HWC2_ATTRIBUTE_WIDTH:
+ return mode.hdisplay;
+
+ case HWC2_ATTRIBUTE_HEIGHT:
+ return mode.vdisplay;
+
+ case HWC2_ATTRIBUTE_DPI_X:
+ return dpi(mode.hdisplay, data.width_mm);
+
+ case HWC2_ATTRIBUTE_DPI_Y:
+ return dpi(mode.vdisplay, data.height_mm);
+
+ default:
+ ALOGE("unknown display attribute %u", attribute);
+ return -EINVAL;
+ }
+}
+
+int adf_getDisplayAttributes_hwc2(struct adf_hwc_helper *dev, int disp,
+ uint32_t config, const uint32_t *attributes, int32_t *values)
+{
+ if ((size_t)disp >= dev->intf_fds.size())
+ return -EINVAL;
+
+ if (config >= dev->display_configs.size())
+ return -EINVAL;
+
+ adf_interface_data data;
+ int err = adf_get_interface_data(dev->intf_fds[disp], &data);
+ if (err < 0) {
+ ALOGE("failed to get ADF interface data: %s", strerror(err));
+ return err;
+ }
+
+ for (int i = 0; attributes[i] != HWC2_ATTRIBUTE_INVALID; i++)
+ values[i] = adf_display_attribute_hwc2(data,
+ dev->display_configs[config], attributes[i]);
+
+ adf_free_interface_data(&data);
+ return 0;
+}
+
+int adf_set_active_config_hwc2(struct adf_hwc_helper *dev, int disp,
+ uint32_t config)
+{
+ if ((size_t)disp >= dev->intf_fds.size())
+ return -EINVAL;
+
+ if (config >= dev->display_configs.size())
+ return -EINVAL;
+
+ struct drm_mode_modeinfo mode = dev->display_configs[config];
+
+ return adf_interface_set_mode(dev->intf_fds[disp], &mode);
+}
+
static void handle_adf_event(struct adf_hwc_helper *dev, int disp)
{
adf_event *event;
@@ -208,28 +273,39 @@
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
- pollfd *fds = new pollfd[dev->intf_fds.size()];
+ struct sigaction action = { };
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = 0;
+ action.sa_handler = [](int) { pthread_exit(0); };
+
+ if (sigaction(SIGUSR2, &action, NULL) < 0) {
+ ALOGE("failed to set thread exit action %s", strerror(errno));
+ return NULL;
+ }
+
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGUSR2);
+
+ pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+
+ pollfd fds[dev->intf_fds.size()];
for (size_t i = 0; i < dev->intf_fds.size(); i++) {
fds[i].fd = dev->intf_fds[i];
fds[i].events = POLLIN | POLLPRI;
}
while (true) {
- int err = poll(fds, dev->intf_fds.size(), -1);
-
- if (err > 0) {
- for (size_t i = 0; i < dev->intf_fds.size(); i++)
- if (fds[i].revents & (POLLIN | POLLPRI))
- handle_adf_event(dev, i);
- }
- else if (err == -1) {
- if (errno == EINTR)
- break;
+ if (TEMP_FAILURE_RETRY(poll(fds, dev->intf_fds.size(), -1)) < 0) {
ALOGE("error in event thread: %s", strerror(errno));
+ break;
}
+
+ for (size_t i = 0; i < dev->intf_fds.size(); i++)
+ if (fds[i].revents & (POLLIN | POLLPRI))
+ handle_adf_event(dev, i);
}
- delete [] fds;
return NULL;
}
@@ -264,6 +340,12 @@
}
}
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGUSR2);
+
+ pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+
ret = pthread_create(&dev_ret->event_thread, NULL, adf_event_thread,
dev_ret);
if (ret) {
@@ -284,7 +366,7 @@
void adf_hwc_close(struct adf_hwc_helper *dev)
{
- pthread_kill(dev->event_thread, SIGTERM);
+ pthread_kill(dev->event_thread, SIGUSR2);
pthread_join(dev->event_thread, NULL);
for (size_t i = 0; i < dev->intf_fds.size(); i++)
diff --git a/adf/libadfhwc/include/adfhwc/adfhwc.h b/adf/libadfhwc/include/adfhwc/adfhwc.h
index 71e7624..4f70925 100644
--- a/adf/libadfhwc/include/adfhwc/adfhwc.h
+++ b/adf/libadfhwc/include/adfhwc/adfhwc.h
@@ -23,6 +23,7 @@
#include <video/adf.h>
#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer2.h>
struct adf_hwc_helper;
@@ -123,6 +124,16 @@
uint32_t *configs, size_t *numConfigs);
int adf_getDisplayAttributes(struct adf_hwc_helper *dev, int disp,
uint32_t config, const uint32_t *attributes, int32_t *values);
+/**
+ * Generic implementation of common HWC2 functions.
+ *
+ * The HWC2 should not return these functions directly through getFunction.
+ * Instead, the HWC2 should return stub functions which call these helpers.
+ */
+int adf_getDisplayAttributes_hwc2(struct adf_hwc_helper *dev, int disp,
+ uint32_t config, const uint32_t *attributes, int32_t *values);
+int adf_set_active_config_hwc2(struct adf_hwc_helper *dev, int disp,
+ uint32_t config);
__END_DECLS
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 81d70df..f2975d1 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -45,42 +45,6 @@
return true;
}
-static bool check_dumpable(pid_t pid) {
- // /proc/<pid> is owned by the effective UID of the process.
- // Ownership of most of the other files in /proc/<pid> varies based on PR_SET_DUMPABLE.
- // If PR_GET_DUMPABLE would return 0, they're owned by root, instead.
- std::string proc_pid_path = android::base::StringPrintf("/proc/%d/", pid);
- std::string proc_pid_status_path = proc_pid_path + "/status";
-
- unique_fd proc_pid_fd(open(proc_pid_path.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC));
- if (proc_pid_fd == -1) {
- return false;
- }
- unique_fd proc_pid_status_fd(openat(proc_pid_fd, "status", O_RDONLY | O_CLOEXEC));
- if (proc_pid_status_fd == -1) {
- return false;
- }
-
- struct stat proc_pid_st;
- struct stat proc_pid_status_st;
- if (fstat(proc_pid_fd.get(), &proc_pid_st) != 0 ||
- fstat(proc_pid_status_fd.get(), &proc_pid_status_st) != 0) {
- return false;
- }
-
- // We can't figure out if a process is dumpable if its effective UID is root, but that's fine
- // because being root bypasses the PR_SET_DUMPABLE check for ptrace.
- if (proc_pid_st.st_uid == 0) {
- return true;
- }
-
- if (proc_pid_status_st.st_uid == 0) {
- return false;
- }
-
- return true;
-}
-
bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType dump_type,
int timeout_ms) {
LOG(INFO) << "libdebuggerd_client: started dumping process " << pid;
@@ -114,11 +78,6 @@
return true;
};
- if (!check_dumpable(pid)) {
- dprintf(output_fd.get(), "target pid %d is not dumpable\n", pid);
- return true;
- }
-
sockfd.reset(socket(AF_LOCAL, SOCK_SEQPACKET, 0));
if (sockfd == -1) {
PLOG(ERROR) << "libdebugger_client: failed to create socket";
diff --git a/init/Android.mk b/init/Android.mk
index 18cbedc..2fc6f19 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -107,6 +107,24 @@
libnl \
libavb
+# Include SELinux policy. We do this here because different modules
+# need to be included based on the value of PRODUCT_FULL_TREBLE. This
+# type of conditional inclusion cannot be done in top-level files such
+# as build/target/product/embedded.mk.
+# This conditional inclusion closely mimics the conditional logic
+# inside init/init.cpp for loading SELinux policy from files.
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+# Use split SELinux policy
+LOCAL_REQUIRED_MODULES += \
+ mapping_sepolicy.cil \
+ nonplat_sepolicy.cil \
+ plat_sepolicy.cil \
+ secilc
+else
+# Use monolithic SELinux policy
+LOCAL_REQUIRED_MODULES += sepolicy
+endif
+
# Create symlinks.
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
diff --git a/init/init.cpp b/init/init.cpp
index ad40426..53e7482 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -43,6 +43,7 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
#include <cutils/fs.h>
#include <cutils/iosched_policy.h>
#include <cutils/list.h>
@@ -618,6 +619,133 @@
return 0;
}
+/*
+ * Forks, executes the provided program in the child, and waits for the completion in the parent.
+ *
+ * Returns true if the child exited with status code 0, returns false otherwise.
+ */
+static bool fork_execve_and_wait_for_completion(const char* filename, char* const argv[],
+ char* const envp[]) {
+ pid_t child_pid = fork();
+ if (child_pid == -1) {
+ PLOG(ERROR) << "Failed to fork for " << filename;
+ return false;
+ }
+
+ if (child_pid == 0) {
+ // fork succeeded -- this is executing in the child process
+ if (execve(filename, argv, envp) == -1) {
+ PLOG(ERROR) << "Failed to execve " << filename;
+ return false;
+ }
+ // Unreachable because execve will have succeeded and replaced this code
+ // with child process's code.
+ _exit(127);
+ return false;
+ } else {
+ // fork succeeded -- this is executing in the original/parent process
+ int status;
+ if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
+ PLOG(ERROR) << "Failed to wait for " << filename;
+ return false;
+ }
+
+ if (WIFEXITED(status)) {
+ int status_code = WEXITSTATUS(status);
+ if (status_code == 0) {
+ return true;
+ } else {
+ LOG(ERROR) << filename << " exited with status " << status_code;
+ }
+ } else if (WIFSIGNALED(status)) {
+ LOG(ERROR) << filename << " killed by signal " << WTERMSIG(status);
+ } else if (WIFSTOPPED(status)) {
+ LOG(ERROR) << filename << " stopped by signal " << WSTOPSIG(status);
+ } else {
+ LOG(ERROR) << "waitpid for " << filename << " returned unexpected status: " << status;
+ }
+
+ return false;
+ }
+}
+
+static constexpr const char plat_policy_cil_file[] = "/plat_sepolicy.cil";
+
+static bool selinux_is_split_policy_device() { return access(plat_policy_cil_file, R_OK) != -1; }
+
+/*
+ * Loads SELinux policy split across platform/system and non-platform/vendor files.
+ *
+ * Returns true upon success, false otherwise (failure cause is logged).
+ */
+static bool selinux_load_split_policy() {
+ // IMPLEMENTATION NOTE: Split policy consists of three CIL files:
+ // * platform -- policy needed due to logic contained in the system image,
+ // * non-platform -- policy needed due to logic contained in the vendor image,
+ // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
+ // with newer versions of platform policy.
+ //
+ // secilc is invoked to compile the above three policy files into a single monolithic policy
+ // file. This file is then loaded into the kernel.
+
+ LOG(INFO) << "Compiling SELinux policy";
+
+ // We store the output of the compilation on /dev because this is the most convenient tmpfs
+ // storage mount available this early in the boot sequence.
+ char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
+ android::base::unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
+ if (compiled_sepolicy_fd < 0) {
+ PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
+ return false;
+ }
+
+ const char* compile_args[] = {"/system/bin/secilc", plat_policy_cil_file, "-M", "true", "-c",
+ "30", // TODO: pass in SELinux policy version from build system
+ "/mapping_sepolicy.cil", "/nonplat_sepolicy.cil", "-o",
+ compiled_sepolicy,
+ // We don't care about file_contexts output by the compiler
+ "-f", "/sys/fs/selinux/null", // /dev/null is not yet available
+ nullptr};
+
+ if (!fork_execve_and_wait_for_completion(compile_args[0], (char**)compile_args, (char**)ENV)) {
+ unlink(compiled_sepolicy);
+ return false;
+ }
+ unlink(compiled_sepolicy);
+
+ LOG(INFO) << "Loading compiled SELinux policy";
+ if (selinux_android_load_policy_from_fd(compiled_sepolicy_fd, compiled_sepolicy) < 0) {
+ LOG(ERROR) << "Failed to load SELinux policy from " << compiled_sepolicy;
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Loads SELinux policy from a monolithic file.
+ *
+ * Returns true upon success, false otherwise (failure cause is logged).
+ */
+static bool selinux_load_monolithic_policy() {
+ LOG(VERBOSE) << "Loading SELinux policy from monolithic file";
+ if (selinux_android_load_policy() < 0) {
+ PLOG(ERROR) << "Failed to load monolithic SELinux policy";
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Loads SELinux policy into the kernel.
+ *
+ * Returns true upon success, false otherwise (failure cause is logged).
+ */
+static bool selinux_load_policy() {
+ return selinux_is_split_policy_device() ? selinux_load_split_policy()
+ : selinux_load_monolithic_policy();
+}
+
static void selinux_initialize(bool in_kernel_domain) {
Timer t;
@@ -628,10 +756,9 @@
selinux_set_callback(SELINUX_CB_AUDIT, cb);
if (in_kernel_domain) {
- LOG(INFO) << "Loading SELinux policy...";
- if (selinux_android_load_policy() < 0) {
- PLOG(ERROR) << "failed to load policy";
- security_failure();
+ LOG(INFO) << "Loading SELinux policy";
+ if (!selinux_load_policy()) {
+ panic();
}
bool kernel_enforcing = (security_getenforce() == 1);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index decd644..d88b72e 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -609,8 +609,7 @@
load_override_properties();
/* Read persistent properties after all default values have been loaded. */
load_persistent_properties();
- uint64_t start_ns = boot_clock::now().time_since_epoch().count();
- property_set("ro.boottime.persistent_properties", StringPrintf("%" PRIu64, start_ns).c_str());
+ property_set("ro.persistent_properties.ready", "true");
}
void load_recovery_id_prop() {
diff --git a/libmemtrack/memtrack.cpp b/libmemtrack/memtrack.cpp
index e83f181..c5e74c1 100644
--- a/libmemtrack/memtrack.cpp
+++ b/libmemtrack/memtrack.cpp
@@ -31,6 +31,7 @@
using android::hardware::memtrack::V1_0::MemtrackFlag;
using android::hardware::memtrack::V1_0::MemtrackStatus;
using android::hardware::hidl_vec;
+using android::hardware::Return;
struct memtrack_proc_type {
MemtrackType type;
@@ -69,7 +70,7 @@
if (memtrack == nullptr)
return -1;
- memtrack->getMemory(pid, type,
+ Return<void> ret = memtrack->getMemory(pid, type,
[&t, &err](MemtrackStatus status, hidl_vec<MemtrackRecord> records) {
if (status != MemtrackStatus::SUCCESS) {
err = -1;
@@ -81,7 +82,7 @@
t->records[i].flags = records[i].flags;
}
});
- return err;
+ return ret.isOk() ? err : -1;
}
/* TODO: sanity checks on return values from HALs:
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index d67dee5..077332a 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -67,8 +67,8 @@
std::vector<const char*> argv_hold;
std::vector<std::string> envs;
std::vector<const char*> envp_hold;
- int output_fd; // duplication of fileno(output) (below)
- int error_fd; // duplication of fileno(error) (below)
+ int output_fd; // duplication of fileno(output) (below)
+ int error_fd; // duplication of fileno(error) (below)
// library
int fds[2]; // From popen call
@@ -108,7 +108,7 @@
context = (android_logcat_context_internal*)calloc(
1, sizeof(android_logcat_context_internal));
- if (!context) return NULL;
+ if (!context) return nullptr;
context->fds[0] = -1;
context->fds[1] = -1;
@@ -139,10 +139,10 @@
log_device_t(const char* d, bool b) {
device = d;
binary = b;
- next = NULL;
+ next = nullptr;
printed = false;
- logger = NULL;
- logger_list = NULL;
+ logger = nullptr;
+ logger_list = nullptr;
}
};
@@ -162,7 +162,7 @@
static void close_output(android_logcat_context_internal* context) {
// split output_from_error
if (context->error == context->output) {
- context->output = NULL;
+ context->output = nullptr;
context->output_fd = -1;
}
if (context->error && (context->output_fd == fileno(context->error))) {
@@ -182,7 +182,7 @@
}
fclose(context->output);
}
- context->output = NULL;
+ context->output = nullptr;
}
if (context->output_fd >= 0) {
if (context->output_fd != fileno(stdout)) {
@@ -198,7 +198,7 @@
static void close_error(android_logcat_context_internal* context) {
// split error_from_output
if (context->output == context->error) {
- context->error = NULL;
+ context->error = nullptr;
context->error_fd = -1;
}
if (context->output && (context->error_fd == fileno(context->output))) {
@@ -218,14 +218,12 @@
}
fclose(context->error);
}
- context->error = NULL;
+ context->error = nullptr;
}
if (context->error_fd >= 0) {
if ((context->error_fd != fileno(stdout)) &&
(context->error_fd != fileno(stderr))) {
- if (context->fds[1] == context->error_fd) {
- context->fds[1] = -1;
- }
+ if (context->fds[1] == context->error_fd) context->fds[1] = -1;
close(context->error_fd);
}
context->error_fd = -1;
@@ -236,9 +234,7 @@
int err;
// Can't rotate logs if we're not outputting to a file
- if (context->outputFileName == NULL) {
- return;
- }
+ if (!context->outputFileName) return;
close_output(context);
@@ -257,7 +253,7 @@
"%s.%.*d", context->outputFileName, maxRotationCountDigits, i);
std::string file0;
- if (i - 1 == 0) {
+ if (!(i - 1)) {
file0 = android::base::StringPrintf("%s", context->outputFileName);
} else {
file0 =
@@ -265,7 +261,7 @@
maxRotationCountDigits, i - 1);
}
- if ((file0.length() == 0) || (file1.length() == 0)) {
+ if (!file0.length() || !file1.length()) {
perror("while rotating log files");
break;
}
@@ -284,7 +280,7 @@
return;
}
context->output = fdopen(context->output_fd, "web");
- if (context->output == NULL) {
+ if (!context->output) {
logcat_panic(context, HELP_FALSE, "couldn't fdopen output file");
return;
}
@@ -305,9 +301,7 @@
static bool regexOk(android_logcat_context_internal* context,
const AndroidLogEntry& entry) {
- if (!context->regex) {
- return true;
- }
+ if (!context->regex) return true;
std::string messageString(entry.message, entry.messageLen);
@@ -323,7 +317,7 @@
if (dev->binary) {
if (!context->eventTagMap && !context->hasOpenedEventTagMap) {
- context->eventTagMap = android_openEventTagMap(NULL);
+ context->eventTagMap = android_openEventTagMap(nullptr);
context->hasOpenedEventTagMap = true;
}
err = android_log_processBinaryLogBuffer(
@@ -334,9 +328,7 @@
} else {
err = android_log_processLogBuffer(&buf->entry_v1, &entry);
}
- if ((err < 0) && !context->debug) {
- return;
- }
+ if ((err < 0) && !context->debug) return;
if (android_log_shouldPrintLine(
context->logformat, std::string(entry.tag, entry.tagLen).c_str(),
@@ -381,7 +373,7 @@
static void setupOutputAndSchedulingPolicy(
android_logcat_context_internal* context, bool blocking) {
- if (context->outputFileName == NULL) return;
+ if (!context->outputFileName) return;
if (blocking) {
// Lower priority and set to batch scheduling if we are saving
@@ -454,6 +446,8 @@
" and individually flagged modifying adverbs can be added:\n"
" color descriptive epoch monotonic printable uid\n"
" usec UTC year zone\n"
+ " Multiple -v parameters or comma separated list of format and\n"
+ " format modifiers are allowed.\n"
// private and undocumented nsec, no signal, too much noise
// useful for -T or -t <timestamp> accurate testing though.
" -D, --dividers Print dividers between each log buffer\n"
@@ -562,10 +556,8 @@
format = android_log_formatFromString(formatString);
- if (format == FORMAT_OFF) {
- // FORMAT_OFF means invalid string
- return -1;
- }
+ // invalid string?
+ if (format == FORMAT_OFF) return -1;
return android_log_setPrintFormat(context->logformat, format);
}
@@ -592,21 +584,15 @@
// String to unsigned int, returns -1 if it fails
static bool getSizeTArg(const char* ptr, size_t* val, size_t min = 0,
size_t max = SIZE_MAX) {
- if (!ptr) {
- return false;
- }
+ if (!ptr) return false;
char* endp;
errno = 0;
size_t ret = (size_t)strtoll(ptr, &endp, 0);
- if (endp[0] || errno) {
- return false;
- }
+ if (endp[0] || errno) return false;
- if ((ret > max) || (ret < min)) {
- return false;
- }
+ if ((ret > max) || (ret < min)) return false;
*val = ret;
return true;
@@ -642,22 +628,16 @@
static char* parseTime(log_time& t, const char* cp) {
char* ep = t.strptime(cp, "%m-%d %H:%M:%S.%q");
- if (ep) {
- return ep;
- }
+ if (ep) return ep;
ep = t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
- if (ep) {
- return ep;
- }
+ if (ep) return ep;
return t.strptime(cp, "%s.%q");
}
// Find last logged line in <outputFileName>, or <outputFileName>.1
static log_time lastLogTime(char* outputFileName) {
log_time retval(log_time::EPOCH);
- if (!outputFileName) {
- return retval;
- }
+ if (!outputFileName) return retval;
std::string directory;
char* file = strrchr(outputFileName, '/');
@@ -673,9 +653,7 @@
std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(directory.c_str()),
closedir);
- if (!dir.get()) {
- return retval;
- }
+ if (!dir.get()) return retval;
log_time now(android_log_clockid());
@@ -683,10 +661,10 @@
log_time modulo(0, NS_PER_SEC);
struct dirent* dp;
- while ((dp = readdir(dir.get())) != NULL) {
- if ((dp->d_type != DT_REG) || (strncmp(dp->d_name, file, len) != 0) ||
+ while (!!(dp = readdir(dir.get()))) {
+ if ((dp->d_type != DT_REG) || !!strncmp(dp->d_name, file, len) ||
(dp->d_name[len] && ((dp->d_name[len] != '.') ||
- (strtoll(dp->d_name + 1, NULL, 10) != 1)))) {
+ (strtoll(dp->d_name + 1, nullptr, 10) != 1)))) {
continue;
}
@@ -694,17 +672,13 @@
file_name += "/";
file_name += dp->d_name;
std::string file;
- if (!android::base::ReadFileToString(file_name, &file)) {
- continue;
- }
+ if (!android::base::ReadFileToString(file_name, &file)) continue;
bool found = false;
for (const auto& line : android::base::Split(file, "\n")) {
log_time t(log_time::EPOCH);
char* ep = parseTime(t, line.c_str());
- if (!ep || (*ep != ' ')) {
- continue;
- }
+ if (!ep || (*ep != ' ')) continue;
// determine the time precision of the logs (eg: msec or usec)
for (unsigned long mod = 1UL; mod < modulo.tv_nsec; mod *= 10) {
if (t.tv_nsec % (mod * 10)) {
@@ -722,13 +696,9 @@
}
}
// We count on the basename file to be the definitive end, so stop here.
- if (!dp->d_name[len] && found) {
- break;
- }
+ if (!dp->d_name[len] && found) break;
}
- if (retval == log_time::EPOCH) {
- return retval;
- }
+ if (retval == log_time::EPOCH) return retval;
// tail_time prints matching or higher, round up by the modulo to prevent
// a replay of the last entry we have just checked.
retval += modulo;
@@ -736,32 +706,29 @@
}
const char* getenv(android_logcat_context_internal* context, const char* name) {
- if (!context->envp || !name || !*name) return NULL;
+ if (!context->envp || !name || !*name) return nullptr;
for (size_t len = strlen(name), i = 0; context->envp[i]; ++i) {
if (strncmp(context->envp[i], name, len)) continue;
if (context->envp[i][len] == '=') return &context->envp[i][len + 1];
}
- return NULL;
+ return nullptr;
}
} // namespace android
void reportErrorName(const char** current, const char* name,
bool blockSecurity) {
- if (*current) {
- return;
+ if (*current) return;
+ if (!blockSecurity || (android_name_to_log_id(name) != LOG_ID_SECURITY)) {
+ *current = name;
}
- if (blockSecurity && (android_name_to_log_id(name) == LOG_ID_SECURITY)) {
- return;
- }
- *current = name;
}
static int __logcat(android_logcat_context_internal* context) {
using namespace android;
int err;
- int hasSetLogFormat = 0;
+ bool hasSetLogFormat = false;
bool clearLog = false;
bool allSelected = false;
bool getLogSize = false;
@@ -769,11 +736,11 @@
bool printStatistics = false;
bool printDividers = false;
unsigned long setLogSize = 0;
- char* setPruneList = NULL;
- char* setId = NULL;
+ char* setPruneList = nullptr;
+ char* setId = nullptr;
int mode = ANDROID_LOG_RDONLY;
std::string forceFilters;
- log_device_t* devices = NULL;
+ log_device_t* devices = nullptr;
log_device_t* dev;
struct logger_list* logger_list;
size_t tail_lines = 0;
@@ -783,10 +750,10 @@
// object instantiations before goto's can happen
log_device_t unexpected("unexpected", false);
- const char* openDeviceFail = NULL;
- const char* clearFail = NULL;
- const char* setSizeFail = NULL;
- const char* getSizeFail = NULL;
+ const char* openDeviceFail = nullptr;
+ const char* clearFail = nullptr;
+ const char* setSizeFail = nullptr;
+ const char* getSizeFail = nullptr;
int argc = context->argc;
char* const* argv = context->argv;
@@ -813,7 +780,7 @@
break;
}
- const char* filename = NULL;
+ const char* filename = nullptr;
for (int i = 0; i < argc; ++i) {
// Simulate shell stdout redirect parsing
if (argv[i][0] != '>') continue;
@@ -825,13 +792,13 @@
}
// Deal with setting up file descriptors and FILE pointers
- if (context->error_fd >= 0) { // Is an error file descriptor supplied?
+ if (context->error_fd >= 0) { // Is an error file descriptor supplied?
if (context->error_fd == context->output_fd) {
context->stderr_stdout = true;
- } else if (context->stderr_null) { // redirection told us to close it
+ } else if (context->stderr_null) { // redirection told us to close it
close(context->error_fd);
context->error_fd = -1;
- } else { // All Ok, convert error to a FILE pointer
+ } else { // All Ok, convert error to a FILE pointer
context->error = fdopen(context->error_fd, "web");
if (!context->error) {
context->retval = -errno;
@@ -842,11 +809,11 @@
}
}
}
- if (context->output_fd >= 0) { // Is an output file descriptor supplied?
- if (filename) { // redirect to file, close the supplied file descriptor.
+ if (context->output_fd >= 0) { // Is an output file descriptor supplied?
+ if (filename) { // redirect to file, close supplied file descriptor.
close(context->output_fd);
context->output_fd = -1;
- } else { // All Ok, convert output to a FILE pointer
+ } else { // All Ok, convert output to a FILE pointer
context->output = fdopen(context->output_fd, "web");
if (!context->output) {
context->retval = -errno;
@@ -857,7 +824,7 @@
}
}
}
- if (filename) { // We supplied an output file redirected in command line
+ if (filename) { // We supplied an output file redirected in command line
context->output = fopen(filename, "web");
}
// Deal with 2>&1
@@ -865,7 +832,7 @@
// Deal with 2>/dev/null
if (context->stderr_null) {
context->error_fd = -1;
- context->error = NULL;
+ context->error = nullptr;
}
// Only happens if output=stdout or output=filename
if ((context->output_fd < 0) && context->output) {
@@ -878,12 +845,16 @@
context->logformat = android_log_format_new();
- if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
+ if (argc == 2 && !strcmp(argv[1], "--help")) {
show_help(context);
context->retval = EXIT_SUCCESS;
goto exit;
}
+ // meant to catch comma-delimited values, but cast a wider
+ // net for stability dealing with possible mistaken inputs.
+ static const char delimiters[] = ",:; \t\n\r\f";
+
// danger: getopt is _not_ reentrant
optind = 1;
for (;;) {
@@ -898,43 +869,40 @@
static const char print_str[] = "print";
// clang-format off
static const struct option long_options[] = {
- { "binary", no_argument, NULL, 'B' },
- { "buffer", required_argument, NULL, 'b' },
- { "buffer-size", optional_argument, NULL, 'g' },
- { "clear", no_argument, NULL, 'c' },
- { debug_str, no_argument, NULL, 0 },
- { "dividers", no_argument, NULL, 'D' },
- { "file", required_argument, NULL, 'f' },
- { "format", required_argument, NULL, 'v' },
+ { "binary", no_argument, nullptr, 'B' },
+ { "buffer", required_argument, nullptr, 'b' },
+ { "buffer-size", optional_argument, nullptr, 'g' },
+ { "clear", no_argument, nullptr, 'c' },
+ { debug_str, no_argument, nullptr, 0 },
+ { "dividers", no_argument, nullptr, 'D' },
+ { "file", required_argument, nullptr, 'f' },
+ { "format", required_argument, nullptr, 'v' },
// hidden and undocumented reserved alias for --regex
- { "grep", required_argument, NULL, 'e' },
+ { "grep", required_argument, nullptr, 'e' },
// hidden and undocumented reserved alias for --max-count
- { "head", required_argument, NULL, 'm' },
- { id_str, required_argument, NULL, 0 },
- { "last", no_argument, NULL, 'L' },
- { "max-count", required_argument, NULL, 'm' },
- { pid_str, required_argument, NULL, 0 },
- { print_str, no_argument, NULL, 0 },
- { "prune", optional_argument, NULL, 'p' },
- { "regex", required_argument, NULL, 'e' },
- { "rotate-count", required_argument, NULL, 'n' },
- { "rotate-kbytes", required_argument, NULL, 'r' },
- { "statistics", no_argument, NULL, 'S' },
+ { "head", required_argument, nullptr, 'm' },
+ { id_str, required_argument, nullptr, 0 },
+ { "last", no_argument, nullptr, 'L' },
+ { "max-count", required_argument, nullptr, 'm' },
+ { pid_str, required_argument, nullptr, 0 },
+ { print_str, no_argument, nullptr, 0 },
+ { "prune", optional_argument, nullptr, 'p' },
+ { "regex", required_argument, nullptr, 'e' },
+ { "rotate-count", required_argument, nullptr, 'n' },
+ { "rotate-kbytes", required_argument, nullptr, 'r' },
+ { "statistics", no_argument, nullptr, 'S' },
// hidden and undocumented reserved alias for -t
- { "tail", required_argument, NULL, 't' },
+ { "tail", required_argument, nullptr, 't' },
// support, but ignore and do not document, the optional argument
- { wrap_str, optional_argument, NULL, 0 },
- { NULL, 0, NULL, 0 }
+ { wrap_str, optional_argument, nullptr, 0 },
+ { nullptr, 0, nullptr, 0 }
};
// clang-format on
ret = getopt_long(argc, argv,
":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
&option_index);
-
- if (ret < 0) {
- break;
- }
+ if (ret < 0) break;
switch (ret) {
case 0:
@@ -976,8 +944,7 @@
break;
}
if (long_options[option_index].name == id_str) {
- setId = optarg && optarg[0] ? optarg : NULL;
- break;
+ setId = (optarg && optarg[0]) ? optarg : nullptr;
}
break;
@@ -1045,7 +1012,7 @@
break;
case 'm': {
- char* end = NULL;
+ char* end = nullptr;
if (!getSizeTArg(optarg, &context->maxCount)) {
logcat_panic(context, HELP_FALSE,
"-%c \"%s\" isn't an "
@@ -1109,19 +1076,23 @@
break;
case 'b': {
+ std::unique_ptr<char, void (*)(void*)> buffers(strdup(optarg),
+ free);
+ optarg = buffers.get();
unsigned idMask = 0;
- while ((optarg = strtok(optarg, ",:; \t\n\r\f")) != NULL) {
- if (strcmp(optarg, "default") == 0) {
+ char* sv = nullptr; // protect against -ENOMEM above
+ while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
+ if (!strcmp(optarg, "default")) {
idMask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) |
(1 << LOG_ID_CRASH);
- } else if (strcmp(optarg, "all") == 0) {
+ } else if (!strcmp(optarg, "all")) {
allSelected = true;
idMask = (unsigned)-1;
} else {
log_id_t log_id = android_name_to_log_id(optarg);
const char* name = android_log_id_to_name(log_id);
- if (strcmp(name, optarg) != 0) {
+ if (!!strcmp(name, optarg)) {
logcat_panic(context, HELP_TRUE,
"unknown buffer %s\n", optarg);
goto exit;
@@ -1129,19 +1100,15 @@
if (log_id == LOG_ID_SECURITY) allSelected = false;
idMask |= (1 << log_id);
}
- optarg = NULL;
+ optarg = nullptr;
}
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char* name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
- if (log_id != (log_id_t)i) {
- continue;
- }
- if ((idMask & (1 << i)) == 0) {
- continue;
- }
+ if (log_id != (log_id_t)i) continue;
+ if (!(idMask & (1 << i))) continue;
bool found = false;
for (dev = devices; dev; dev = dev->next) {
@@ -1149,13 +1116,9 @@
found = true;
break;
}
- if (!dev->next) {
- break;
- }
+ if (!dev->next) break;
}
- if (found) {
- continue;
- }
+ if (found) continue;
bool binary =
!strcmp(name, "events") || !strcmp(name, "security");
@@ -1176,7 +1139,7 @@
break;
case 'f':
- if ((tail_time == log_time::EPOCH) && (tail_lines == 0)) {
+ if ((tail_time == log_time::EPOCH) && !tail_lines) {
tail_time = lastLogTime(optarg);
}
// redirect output to a file
@@ -1199,20 +1162,28 @@
}
break;
- case 'v':
+ case 'v': {
if (!strcmp(optarg, "help") || !strcmp(optarg, "--help")) {
show_format_help(context);
context->retval = EXIT_SUCCESS;
goto exit;
}
- err = setLogFormat(context, optarg);
- if (err < 0) {
- logcat_panic(context, HELP_FORMAT,
- "Invalid parameter \"%s\" to -v\n", optarg);
- goto exit;
+ std::unique_ptr<char, void (*)(void*)> formats(strdup(optarg),
+ free);
+ optarg = formats.get();
+ unsigned idMask = 0;
+ char* sv = nullptr; // protect against -ENOMEM above
+ while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
+ err = setLogFormat(context, optarg);
+ if (err < 0) {
+ logcat_panic(context, HELP_FORMAT,
+ "Invalid parameter \"%s\" to -v\n", optarg);
+ goto exit;
+ }
+ optarg = nullptr;
+ if (err) hasSetLogFormat = true;
}
- hasSetLogFormat |= err;
- break;
+ } break;
case 'Q':
#define KERNEL_OPTION "androidboot.logcat="
@@ -1319,13 +1290,13 @@
}
}
- if (context->logRotateSizeKBytes != 0 && context->outputFileName == NULL) {
+ if (!!context->logRotateSizeKBytes && !context->outputFileName) {
logcat_panic(context, HELP_TRUE, "-r requires -f as well\n");
goto exit;
}
- if (setId != NULL) {
- if (context->outputFileName == NULL) {
+ if (!!setId) {
+ if (!context->outputFileName) {
logcat_panic(context, HELP_TRUE,
"--id='%s' requires -f as well\n", setId);
goto exit;
@@ -1337,22 +1308,29 @@
bool file_ok = android::base::ReadFileToString(file_name, &file);
android::base::WriteStringToFile(setId, file_name, S_IRUSR | S_IWUSR,
getuid(), getgid());
- if (!file_ok || (file.compare(setId) == 0)) {
- setId = NULL;
- }
+ if (!file_ok || !file.compare(setId)) setId = nullptr;
}
- if (hasSetLogFormat == 0) {
+ if (!hasSetLogFormat) {
const char* logFormat = android::getenv(context, "ANDROID_PRINTF_LOG");
- if (logFormat != NULL) {
- err = setLogFormat(context, logFormat);
- if ((err < 0) && context->error) {
- fprintf(context->error,
- "invalid format in ANDROID_PRINTF_LOG '%s'\n",
- logFormat);
+ if (!!logFormat) {
+ std::unique_ptr<char, void (*)(void*)> formats(strdup(logFormat),
+ free);
+ char* sv = nullptr; // protect against -ENOMEM above
+ char* arg = formats.get();
+ while (!!(arg = strtok_r(arg, delimiters, &sv))) {
+ err = setLogFormat(context, arg);
+ // environment should not cause crash of logcat
+ if ((err < 0) && context->error) {
+ fprintf(context->error,
+ "invalid format in ANDROID_PRINTF_LOG '%s'\n", arg);
+ }
+ arg = nullptr;
+ if (err > 0) hasSetLogFormat = true;
}
- } else {
+ }
+ if (!hasSetLogFormat) {
setLogFormat(context, "threadtime");
}
}
@@ -1369,7 +1347,7 @@
// Add from environment variable
const char* env_tags_orig = android::getenv(context, "ANDROID_LOG_TAGS");
- if (env_tags_orig != NULL) {
+ if (!!env_tags_orig) {
err = android_log_addFilterString(context->logformat,
env_tags_orig);
@@ -1424,7 +1402,7 @@
for (int i = context->maxRotatedLogs ; i >= 0 ; --i) {
std::string file;
- if (i == 0) {
+ if (!i) {
file = android::base::StringPrintf(
"%s", context->outputFileName);
} else {
@@ -1432,7 +1410,7 @@
context->outputFileName, maxRotationCountDigits, i);
}
- if (file.length() == 0) {
+ if (!file.length()) {
perror("while clearing log files");
reportErrorName(&clearFail, dev->device, allSelected);
break;
@@ -1440,7 +1418,7 @@
err = unlink(file.c_str());
- if (err < 0 && errno != ENOENT && clearFail == NULL) {
+ if (err < 0 && errno != ENOENT && !clearFail) {
perror("while clearing log files");
reportErrorName(&clearFail, dev->device, allSelected);
}
@@ -1507,7 +1485,7 @@
size_t len = strlen(setPruneList);
// extra 32 bytes are needed by android_logger_set_prune_list
size_t bLen = len + 32;
- char* buf = NULL;
+ char* buf = nullptr;
if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {
buf[len] = '\0';
if (android_logger_set_prune_list(logger_list, buf, bLen)) {
@@ -1527,7 +1505,7 @@
char* buf;
for (int retry = 32; (retry >= 0) && ((buf = new char[len]));
- delete[] buf, buf = NULL, --retry) {
+ delete[] buf, buf = nullptr, --retry) {
if (getPruneList) {
android_logger_get_prune_list(logger_list, buf, len);
} else {
@@ -1536,7 +1514,7 @@
buf[len - 1] = '\0';
if (atol(buf) < 3) {
delete[] buf;
- buf = NULL;
+ buf = nullptr;
break;
}
size_t ret = atol(buf) + 1;
@@ -1556,19 +1534,13 @@
char* cp = buf + len - 1;
*cp = '\0';
bool truncated = *--cp != '\f';
- if (!truncated) {
- *cp = '\0';
- }
+ if (!truncated) *cp = '\0';
// squash out the byte count
cp = buf;
if (!truncated) {
- while (isdigit(*cp)) {
- ++cp;
- }
- if (*cp == '\n') {
- ++cp;
- }
+ while (isdigit(*cp)) ++cp;
+ if (*cp == '\n') ++cp;
}
len = strlen(cp);
@@ -1577,32 +1549,28 @@
goto close;
}
- if (getLogSize || setLogSize || clearLog) {
- goto close;
- }
+ if (getLogSize || setLogSize || clearLog) goto close;
- setupOutputAndSchedulingPolicy(context, (mode & ANDROID_LOG_NONBLOCK) == 0);
+ setupOutputAndSchedulingPolicy(context, !(mode & ANDROID_LOG_NONBLOCK));
if (context->stop) goto close;
// LOG_EVENT_INT(10, 12345);
// LOG_EVENT_LONG(11, 0x1122334455667788LL);
// LOG_EVENT_STRING(0, "whassup, doc?");
- dev = NULL;
+ dev = nullptr;
while (!context->stop &&
(!context->maxCount || (context->printCount < context->maxCount))) {
struct log_msg log_msg;
int ret = android_logger_list_read(logger_list, &log_msg);
- if (ret == 0) {
+ if (!ret) {
logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
break;
}
if (ret < 0) {
- if (ret == -EAGAIN) {
- break;
- }
+ if (ret == -EAGAIN) break;
if (ret == -EIO) {
logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
@@ -1618,9 +1586,7 @@
log_device_t* d;
for (d = devices; d; d = d->next) {
- if (android_name_to_log_id(d->device) == log_msg.id()) {
- break;
- }
+ if (android_name_to_log_id(d->device) == log_msg.id()) break;
}
if (!d) {
context->devCount = 2; // set to Multiple
@@ -1686,9 +1652,7 @@
android_logcat_context_internal* context = ctx;
int save_errno = EBUSY;
- if ((context->fds[0] >= 0) || (context->fds[1] >= 0)) {
- goto exit;
- }
+ if ((context->fds[0] >= 0) || (context->fds[1] >= 0)) goto exit;
if (pipe(context->fds) < 0) {
save_errno = errno;
@@ -1725,11 +1689,11 @@
for (auto& str : context->args) {
context->argv_hold.push_back(str.c_str());
}
- context->argv_hold.push_back(NULL);
+ context->argv_hold.push_back(nullptr);
for (auto& str : context->envs) {
context->envp_hold.push_back(str.c_str());
}
- context->envp_hold.push_back(NULL);
+ context->envp_hold.push_back(nullptr);
context->argc = context->argv_hold.size() - 1;
context->argv = (char* const*)&context->argv_hold[0];
@@ -1738,7 +1702,7 @@
#ifdef DEBUG
fprintf(stderr, "argv[%d] = {", context->argc);
for (auto str : context->argv_hold) {
- fprintf(stderr, " \"%s\"", str ?: "NULL");
+ fprintf(stderr, " \"%s\"", str ?: "nullptr");
}
fprintf(stderr, " }\n");
fflush(stderr);
@@ -1784,11 +1748,14 @@
int android_logcat_destroy(android_logcat_context* ctx) {
android_logcat_context_internal* context = *ctx;
- *ctx = NULL;
+ if (!context) return -EBADF;
+
+ *ctx = nullptr;
context->stop = true;
while (context->thread_stopped == false) {
+ // Makes me sad, replace thread_stopped with semaphore. Short lived.
sched_yield();
}