Merge "Revert "Create command to run adb tests and output results""
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..fc4eb1b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+AccessModifierOffset: -2
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/adb/NOTICE b/adb/NOTICE
index 9ffcc08..ff47c95 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,3 +189,63 @@
END OF TERMS AND CONDITIONS
+------------------------------------------------------------
+libwinpthread license:
+------------------------------------------------------------
+Copyright (c) 2011 mingw-w64 project
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Lockless Inc. nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index c08b922..92e9039 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -283,6 +283,8 @@
D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
goto err;
}
+ //Signal only when writing the descriptors to ffs
+ android::base::SetProperty("sys.usb.ffs.ready", "1");
}
h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
@@ -358,7 +360,6 @@
}
std::this_thread::sleep_for(1s);
}
- android::base::SetProperty("sys.usb.ffs.ready", "1");
D("[ usb_thread - registering device ]");
register_usb_transport(usb, 0, 0, 1);
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index e16cf12..516b4f2 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -102,7 +102,7 @@
#if defined(_WIN32) || !ADB_HOST
return false;
#else
- static bool enable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "1") == 0;
- return enable;
+ static bool disable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "0") == 0;
+ return !disable;
#endif
}
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 4727894..f73f672 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -48,6 +48,7 @@
shared_libs: [
"libbase",
"liblog",
+ "libseccomp_policy",
],
multilib: {
lib32: {
@@ -69,6 +70,7 @@
"libdebuggerd_handler",
"libbase",
"liblog",
+ "libseccomp_policy",
],
multilib: {
lib32: {
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 1c01e3e..6970201 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -33,6 +33,8 @@
#include <android-base/logging.h>
#include <log/log.h>
+#include "seccomp_policy.h"
+
#if defined(STATIC_CRASHER)
#include "debuggerd/handler.h"
#endif
@@ -269,6 +271,7 @@
munmap(map, sizeof(int));
map[0] = '8';
} else if (!strcasecmp(arg, "seccomp")) {
+ set_seccomp_filter();
syscall(99999);
#if defined(__arm__)
} else if (!strcasecmp(arg, "kuser_helper_version")) {
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 0c5d3cf..492e9f0 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -34,6 +34,8 @@
static void usage(int exit_code) {
fprintf(stderr, "usage: debuggerd [-b] PID\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "-b, --backtrace just a backtrace rather than a full tombstone\n");
_exit(exit_code);
}
@@ -56,7 +58,8 @@
int main(int argc, char* argv[]) {
if (argc <= 1) usage(0);
if (argc > 3) usage(1);
- if (argc == 3 && strcmp(argv[1], "-b") != 0) usage(1);
+ if (argc == 3 && strcmp(argv[1], "-b") != 0 && strcmp(argv[1], "--backtrace") != 0) usage(1);
+ bool backtrace_only = argc == 3;
pid_t pid;
if (!android::base::ParseInt(argv[argc - 1], &pid, 1, std::numeric_limits<pid_t>::max())) {
@@ -69,9 +72,8 @@
}
std::thread redirect_thread = spawn_redirect_thread(std::move(piperead));
- bool backtrace = argc == 3;
if (!debuggerd_trigger_dump(pid, std::move(pipewrite),
- backtrace ? kDebuggerdBacktrace : kDebuggerdTombstone, 0)) {
+ backtrace_only ? kDebuggerdBacktrace : kDebuggerdTombstone, 0)) {
redirect_thread.join();
errx(1, "failed to dump process %d", pid);
}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 3166bfc..4686bfd 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -214,7 +214,8 @@
cause = "call to kuser_cmpxchg64";
}
} else if (si.si_signo == SIGSYS && si.si_code == SYS_SECCOMP) {
- cause = StringPrintf("seccomp prevented call to disallowed system call %d", si.si_syscall);
+ cause = StringPrintf("seccomp prevented call to disallowed %s system call %d",
+ ABI_STRING, si.si_syscall);
}
if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str());
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 57209aa..744cd72 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -41,6 +41,7 @@
return false;
}
+__attribute__((__weak__, visibility("default")))
void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
bool write_to_tombstone = (log->tfd != -1);
bool write_to_logcat = is_allowed_in_logcat(ltype)
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 8705ece..6754508 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -34,6 +34,7 @@
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
+#include "debuggerd/handler.h"
#include "debuggerd/protocol.h"
#include "debuggerd/util.h"
@@ -116,7 +117,7 @@
}
result.reset(
- openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0700));
+ openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
if (result == -1) {
PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
}
@@ -254,6 +255,16 @@
}
int main(int, char* []) {
+ umask(0137);
+
+ // Don't try to connect to ourselves if we crash.
+ struct sigaction action = {};
+ action.sa_handler = [](int signal) {
+ LOG(ERROR) << "received fatal signal " << signal;
+ _exit(1);
+ };
+ debuggerd_register_handlers(&action);
+
tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (tombstone_directory_fd == -1) {
PLOG(FATAL) << "failed to open tombstone directory";
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index a50817e..d0e4682 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -31,6 +31,8 @@
#include <time.h>
#include <unistd.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include <cutils/partition_utils.h>
@@ -64,6 +66,21 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+// record fs stat
+enum FsStatFlags {
+ FS_STAT_IS_EXT4 = 0x0001,
+ FS_STAT_NEW_IMAGE_VERSION = 0x0002,
+ FS_STAT_E2FSCK_F_ALWAYS = 0x0004,
+ FS_STAT_UNCLEAN_SHUTDOWN = 0x0008,
+ FS_STAT_QUOTA_ENABLED = 0x0010,
+ FS_STAT_TUNE2FS_FAILED = 0x0020,
+ FS_STAT_RO_MOUNT_FAILED = 0x0040,
+ FS_STAT_RO_UNMOUNT_FAILED = 0x0080,
+ FS_STAT_FULL_MOUNT_FAILED = 0x0100,
+ FS_STAT_E2FSCK_FAILED = 0x0200,
+ FS_STAT_E2FSCK_FS_FIXED = 0x0400,
+};
+
/*
* gettime() - returns the time in seconds of the system's monotonic clock or
* zero on error.
@@ -94,7 +111,18 @@
return ret;
}
-static void check_fs(const char *blk_device, char *fs_type, char *target)
+static void log_fs_stat(const char* blk_device, int fs_stat)
+{
+ if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
+ std::string msg = android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device, fs_stat);
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
+ O_APPEND | O_CREAT, 0664)));
+ if (fd == -1 || !android::base::WriteStringToFd(msg, fd)) {
+ LWARNING << __FUNCTION__ << "() cannot log " << msg;
+ }
+}
+
+static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat)
{
int status;
int ret;
@@ -141,10 +169,13 @@
<< ") succeeded";
break;
}
+ *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
PERROR << __FUNCTION__ << "(): umount(" << target << ")="
<< result;
sleep(1);
}
+ } else {
+ *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
}
/*
@@ -157,6 +188,7 @@
} else {
LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
+ *fs_stat |= FS_STAT_E2FSCK_F_ALWAYS;
ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv),
const_cast<char **>(e2fsck_argv),
&status, true, LOG_KLOG | LOG_FILE,
@@ -167,6 +199,10 @@
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
LERROR << "Failed trying to run " << E2FSCK_BIN;
+ *fs_stat |= FS_STAT_E2FSCK_FAILED;
+ } else if (status != 0) {
+ LINFO << "e2fsck returned status 0x" << std::hex << status;
+ *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
}
}
} else if (!strcmp(fs_type, "f2fs")) {
@@ -221,7 +257,8 @@
le32_to_cpu(es->s_r_blocks_count_lo);
}
-static int do_quota(char *blk_device, char *fs_type, struct fstab_rec *rec)
+static int do_quota_with_shutdown_check(char *blk_device, char *fs_type,
+ struct fstab_rec *rec, int *fs_stat)
{
int force_check = 0;
if (!strcmp(fs_type, "ext4")) {
@@ -246,7 +283,16 @@
PERROR << "Can't read '" << blk_device << "' super block";
return force_check;
}
-
+ *fs_stat |= FS_STAT_IS_EXT4;
+ //TODO check if it is new version or not
+ if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 ||
+ (sb.s_state & EXT4_VALID_FS) == 0) {
+ LINFO << __FUNCTION__ << "(): was not clealy shutdown, state flag:"
+ << std::hex << sb.s_state
+ << "incompat flag:" << std::hex << sb.s_feature_incompat;
+ force_check = 1;
+ *fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN;
+ }
int has_quota = (sb.s_feature_ro_compat
& cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
int want_quota = fs_mgr_is_quota(rec) != 0;
@@ -259,6 +305,7 @@
arg1 = "-Oquota";
arg2 = "-Qusrquota,grpquota";
force_check = 1;
+ *fs_stat |= FS_STAT_QUOTA_ENABLED;
} else {
LINFO << "Disabling quota on " << blk_device;
arg1 = "-Q^usrquota,^grpquota";
@@ -282,13 +329,14 @@
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
LERROR << "Failed trying to run " << TUNE2FS_BIN;
+ *fs_stat |= FS_STAT_TUNE2FS_FAILED;
}
}
}
return force_check;
}
-static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
+static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec, int *fs_stat)
{
/* Check for the types of filesystems we know how to check */
if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
@@ -347,6 +395,7 @@
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
LERROR << "Failed trying to run " << TUNE2FS_BIN;
+ *fs_stat |= FS_STAT_TUNE2FS_FAILED;
}
}
}
@@ -487,17 +536,19 @@
continue;
}
- int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- &fstab->recs[i]);
+ int fs_stat = 0;
+ int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
+ fstab->recs[i].fs_type,
+ &fstab->recs[i], &fs_stat);
if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- fstab->recs[i].mount_point);
+ fstab->recs[i].mount_point, &fs_stat);
}
if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- &fstab->recs[i]);
+ &fstab->recs[i], &fs_stat);
}
if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
@@ -511,9 +562,11 @@
<< fstab->recs[start_idx].fs_type;
}
} else {
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
/* back up errno for crypto decisions */
mount_errno = errno;
}
+ log_fs_stat(fstab->recs[i].blk_device, fs_stat);
}
/* Adjust i for the case where it was still withing the recs[] */
@@ -950,16 +1003,18 @@
wait_for_file(n_blk_device, WAIT_TIMEOUT);
}
- int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- &fstab->recs[i]);
+ int fs_stat = 0;
+ int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
+ fstab->recs[i].fs_type,
+ &fstab->recs[i], &fs_stat);
if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
check_fs(n_blk_device, fstab->recs[i].fs_type,
- fstab->recs[i].mount_point);
+ fstab->recs[i].mount_point, &fs_stat);
}
if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
- do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
+ do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat);
}
if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
@@ -996,9 +1051,12 @@
if (__mount(n_blk_device, m, &fstab->recs[i])) {
if (!first_mount_errno) first_mount_errno = errno;
mount_errors++;
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+ log_fs_stat(fstab->recs[i].blk_device, fs_stat);
continue;
} else {
ret = 0;
+ log_fs_stat(fstab->recs[i].blk_device, fs_stat);
goto out;
}
}
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index e8ed6a2..54a6f71 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -30,6 +30,7 @@
#include <unistd.h>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <crypto_utils/android_pubkey.h>
@@ -874,6 +875,11 @@
// read verity metadata
if (fec_verity_get_metadata(f, &verity) < 0) {
PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
+ // Allow verity disabled when the device is unlocked without metadata
+ if ("0" == android::base::GetProperty("ro.boot.flash.locked", "")) {
+ retval = FS_MGR_SETUP_VERITY_DISABLED;
+ LWARNING << "Allow invalid metadata when the device is unlocked";
+ }
goto out;
}
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 4007203..4df0af1 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -141,7 +141,6 @@
struct sysfsStringEnumMap supplyTypeMap[] = {
{ "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
{ "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
- { "BMS", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
{ "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
diff --git a/include/system/window.h b/include/system/window.h
index c340773..31a239b 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -317,6 +317,12 @@
* retire info, 0 if it won't.
*/
NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE = 18,
+
+ /*
+ * Returns 1 if the native window is valid, 0 otherwise. native window is valid
+ * if it is safe (i.e. no crash will occur) to call any method on it.
+ */
+ NATIVE_WINDOW_IS_VALID = 19,
};
/* Valid operations for the (*perform)() hook.
@@ -330,6 +336,7 @@
* ANativeWindow.
*/
enum {
+// clang-format off
NATIVE_WINDOW_SET_USAGE = 0,
NATIVE_WINDOW_CONNECT = 1, /* deprecated */
NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
@@ -358,6 +365,9 @@
NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS = 25,
NATIVE_WINDOW_GET_COMPOSITOR_TIMING = 26,
NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27,
+ NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28,
+ NATIVE_WINDOW_GET_HDR_SUPPORT = 29,
+// clang-format on
};
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -1065,6 +1075,16 @@
outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
}
+static inline int native_window_get_wide_color_support(
+ struct ANativeWindow* window, bool* outSupport) {
+ return window->perform(window, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT,
+ outSupport);
+}
+
+static inline int native_window_get_hdr_support(struct ANativeWindow* window,
+ bool* outSupport) {
+ return window->perform(window, NATIVE_WINDOW_GET_HDR_SUPPORT, outSupport);
+}
__END_DECLS
diff --git a/init/Android.mk b/init/Android.mk
index 2fc6f19..5bcfb7b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -119,7 +119,14 @@
mapping_sepolicy.cil \
nonplat_sepolicy.cil \
plat_sepolicy.cil \
+ plat_sepolicy.cil.sha256 \
secilc
+
+# Include precompiled policy, unless told otherwise
+ifneq ($(PRODUCT_PRECOMPILED_SEPOLICY),false)
+LOCAL_REQUIRED_MODULES += precompiled_sepolicy precompiled_sepolicy.plat.sha256
+endif
+
else
# Use monolithic SELinux policy
LOCAL_REQUIRED_MODULES += sepolicy
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 270afcf..507c4a0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -604,20 +604,27 @@
int mount_mode = MOUNT_MODE_DEFAULT;
const char* fstabfile = args[1].c_str();
std::size_t path_arg_end = args.size();
+ const char* prop_post_fix = "default";
for (na = args.size() - 1; na > 1; --na) {
if (args[na] == "--early") {
path_arg_end = na;
queue_event = false;
mount_mode = MOUNT_MODE_EARLY;
+ prop_post_fix = "early";
} else if (args[na] == "--late") {
path_arg_end = na;
import_rc = false;
mount_mode = MOUNT_MODE_LATE;
+ prop_post_fix = "late";
}
}
+ std::string prop_name = android::base::StringPrintf("ro.boottime.init.mount_all.%s",
+ prop_post_fix);
+ Timer t;
int ret = mount_fstab(fstabfile, mount_mode);
+ property_set(prop_name.c_str(), std::to_string(t.duration_ms()).c_str());
if (import_rc) {
/* Paths of .rc files are specified at the 2nd argument and beyond */
diff --git a/init/init.cpp b/init/init.cpp
index 53e7482..38178a7 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -621,11 +621,21 @@
/*
* Forks, executes the provided program in the child, and waits for the completion in the parent.
+ * Child's stderr is captured and logged using LOG(ERROR).
*
* 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[]) {
+ // Create a pipe used for redirecting child process's output.
+ // * pipe_fds[0] is the FD the parent will use for reading.
+ // * pipe_fds[1] is the FD the child will use for writing.
+ int pipe_fds[2];
+ if (pipe(pipe_fds) == -1) {
+ PLOG(ERROR) << "Failed to create pipe";
+ return false;
+ }
+
pid_t child_pid = fork();
if (child_pid == -1) {
PLOG(ERROR) << "Failed to fork for " << filename;
@@ -634,6 +644,18 @@
if (child_pid == 0) {
// fork succeeded -- this is executing in the child process
+
+ // Close the pipe FD not used by this process
+ TEMP_FAILURE_RETRY(close(pipe_fds[0]));
+
+ // Redirect stderr to the pipe FD provided by the parent
+ if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
+ PLOG(ERROR) << "Failed to redirect stderr of " << filename;
+ _exit(127);
+ return false;
+ }
+ TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+
if (execve(filename, argv, envp) == -1) {
PLOG(ERROR) << "Failed to execve " << filename;
return false;
@@ -644,6 +666,30 @@
return false;
} else {
// fork succeeded -- this is executing in the original/parent process
+
+ // Close the pipe FD not used by this process
+ TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+
+ // Log the redirected output of the child process.
+ // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
+ // As a result, we're buffering all output and logging it in one go at the end of the
+ // invocation, instead of logging it as it comes in.
+ const int child_out_fd = pipe_fds[0];
+ std::string child_output;
+ if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
+ PLOG(ERROR) << "Failed to capture full output of " << filename;
+ }
+ TEMP_FAILURE_RETRY(close(child_out_fd));
+ if (!child_output.empty()) {
+ // Log captured output, line by line, because LOG expects to be invoked for each line
+ std::istringstream in(child_output);
+ std::string line;
+ while (std::getline(in, line)) {
+ LOG(ERROR) << filename << ": " << line;
+ }
+ }
+
+ // Wait for child to terminate
int status;
if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
PLOG(ERROR) << "Failed to wait for " << filename;
@@ -669,7 +715,45 @@
}
}
-static constexpr const char plat_policy_cil_file[] = "/plat_sepolicy.cil";
+static bool read_first_line(const char* file, std::string* line) {
+ line->clear();
+
+ std::string contents;
+ if (!android::base::ReadFileToString(file, &contents, true /* follow symlinks */)) {
+ return false;
+ }
+ std::istringstream in(contents);
+ std::getline(in, *line);
+ return true;
+}
+
+static bool selinux_find_precompiled_split_policy(std::string* file) {
+ file->clear();
+
+ static constexpr const char precompiled_sepolicy[] = "/vendor/etc/selinux/precompiled_sepolicy";
+ if (access(precompiled_sepolicy, R_OK) == -1) {
+ return false;
+ }
+ std::string actual_plat_id;
+ if (!read_first_line("/system/etc/selinux/plat_sepolicy.cil.sha256", &actual_plat_id)) {
+ PLOG(INFO) << "Failed to read /system/etc/selinux/plat_sepolicy.cil.sha256";
+ return false;
+ }
+ std::string precompiled_plat_id;
+ if (!read_first_line("/vendor/etc/selinux/precompiled_sepolicy.plat.sha256",
+ &precompiled_plat_id)) {
+ PLOG(INFO) << "Failed to read /vendor/etc/selinux/precompiled_sepolicy.plat.sha256";
+ return false;
+ }
+ if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
+ return false;
+ }
+
+ *file = precompiled_sepolicy;
+ return true;
+}
+
+static constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
static bool selinux_is_split_policy_device() { return access(plat_policy_cil_file, R_OK) != -1; }
@@ -688,6 +772,22 @@
// secilc is invoked to compile the above three policy files into a single monolithic policy
// file. This file is then loaded into the kernel.
+ // Load precompiled policy from vendor image, if a matching policy is found there. The policy
+ // must match the platform policy on the system image.
+ std::string precompiled_sepolicy_file;
+ if (selinux_find_precompiled_split_policy(&precompiled_sepolicy_file)) {
+ android::base::unique_fd fd(
+ open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
+ if (fd != -1) {
+ if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
+ LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
+ return false;
+ }
+ return true;
+ }
+ }
+ // No suitable precompiled policy could be loaded
+
LOG(INFO) << "Compiling SELinux policy";
// We store the output of the compilation on /dev because this is the most convenient tmpfs
@@ -701,7 +801,8 @@
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",
+ "/vendor/etc/selinux/mapping_sepolicy.cil",
+ "/vendor/etc/selinux/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
diff --git a/libbinderwrapper/Android.mk b/libbinderwrapper/Android.mk
index b38d262..c768373 100644
--- a/libbinderwrapper/Android.mk
+++ b/libbinderwrapper/Android.mk
@@ -41,7 +41,7 @@
include $(BUILD_SHARED_LIBRARY)
-# libbinderwrapper_test_support shared library
+# libbinderwrapper_test_support static library
# ========================================================
include $(CLEAR_VARS)
@@ -59,4 +59,4 @@
binder_test_base.cc \
stub_binder_wrapper.cc \
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 310dbf4..bb8c3af 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -26,6 +26,7 @@
"logger_read.c",
"logger_write.c",
"logprint.c",
+ "stderr_write.c",
]
liblog_host_sources = [
"fake_log_device.c",
diff --git a/liblog/config_write.c b/liblog/config_write.c
index 583dcff..6a6c220 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.c
@@ -78,6 +78,29 @@
&fakeLoggerWrite);
#endif
}
+
+ if (__android_log_frontend & LOGGER_STDERR) {
+ extern struct android_log_transport_write stderrLoggerWrite;
+
+ /*
+ * stderr logger should be primary if we can be the only one, or if
+ * already in the primary list. Otherwise land in the persist list.
+ * Remember we can be called here if we are already initialized.
+ */
+ if (list_empty(&__android_log_transport_write)) {
+ __android_log_add_transport(&__android_log_transport_write,
+ &stderrLoggerWrite);
+ } else {
+ struct android_log_transport_write *transp;
+ write_transport_for_each(transp, &__android_log_transport_write) {
+ if (transp == &stderrLoggerWrite) {
+ return;
+ }
+ }
+ __android_log_add_transport(&__android_log_persist_write,
+ &stderrLoggerWrite);
+ }
+ }
}
LIBLOG_HIDDEN void __android_log_config_write_close() {
diff --git a/liblog/include/log/log_frontend.h b/liblog/include/log/log_frontend.h
index 9527779..5efa548 100644
--- a/liblog/include/log/log_frontend.h
+++ b/liblog/include/log/log_frontend.h
@@ -17,11 +17,12 @@
/*
* Logging frontends, bit mask to select features. Function returns selection.
*/
-#define LOGGER_DEFAULT 0x0
-#define LOGGER_LOGD 0x1
-#define LOGGER_KERNEL 0x2 /* Reserved/Deprecated */
-#define LOGGER_NULL 0x4 /* Does not release resources of other selections */
-#define LOGGER_LOCAL 0x8 /* logs sent to local memory */
+#define LOGGER_DEFAULT 0x00
+#define LOGGER_LOGD 0x01
+#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */
+#define LOGGER_NULL 0x04 /* Does not release resources of other selections */
+#define LOGGER_LOCAL 0x08 /* logs sent to local memory */
+#define LOGGER_STDERR 0x10 /* logs sent to stderr */
/* Both return the selected frontend flag mask, or negative errno */
int android_set_log_frontend(int frontend_flag);
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index e149e68..2a97101 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -664,9 +664,9 @@
return retval;
}
- __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+ __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
- frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD;
+ frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
if (__android_log_frontend != frontend_flag) {
__android_log_frontend = frontend_flag;
@@ -695,7 +695,7 @@
if (write_to_log == __write_to_log_null) {
ret = LOGGER_NULL;
} else {
- __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+ __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
ret = __android_log_frontend;
if ((write_to_log != __write_to_log_init) &&
(write_to_log != __write_to_log_daemon)) {
diff --git a/liblog/logprint.c b/liblog/logprint.c
index af52528..4421f83 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -20,9 +20,6 @@
#define HAVE_STRSEP
#endif
-//#ifndef __MINGW32__
-//#include <arpa/inet.h>
-//#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -117,7 +114,7 @@
c = tolower(c);
if (c >= '0' && c <= '9') {
- if (c >= ('0'+ANDROID_LOG_SILENT)) {
+ if (c >= ('0' + ANDROID_LOG_SILENT)) {
pri = ANDROID_LOG_VERBOSE;
} else {
pri = (android_LogPriority)(c - '0');
@@ -397,7 +394,7 @@
}
if(filterExpression[tagNameLength] == ':') {
- pri = filterCharToPri(filterExpression[tagNameLength+1]);
+ pri = filterCharToPri(filterExpression[tagNameLength + 1]);
if (pri == ANDROID_LOG_UNKNOWN) {
goto error;
@@ -521,6 +518,9 @@
struct logger_entry *buf,
AndroidLogEntry *entry)
{
+ entry->message = NULL;
+ entry->messageLen = 0;
+
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
entry->uid = -1;
@@ -621,7 +621,7 @@
low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
- return ((uint64_t) high << 32) | (uint64_t) low;
+ return ((uint64_t)high << 32) | (uint64_t)low;
}
static bool findChar(const char** cp, size_t* len, int c) {
@@ -829,7 +829,10 @@
eventData += 4;
eventDataLen -= 4;
- if (eventDataLen < strLen) return -1;
+ if (eventDataLen < strLen) {
+ result = -1; /* mark truncated */
+ strLen = eventDataLen;
+ }
if (cp && (strLen == 0)) {
/* reset the format if no content */
@@ -840,15 +843,18 @@
memcpy(outBuf, eventData, strLen);
outBuf += strLen;
outBufLen -= strLen;
- } else if (outBufLen > 0) {
- /* copy what we can */
- memcpy(outBuf, eventData, outBufLen);
- outBuf += outBufLen;
- outBufLen -= outBufLen;
- goto no_room;
+ } else {
+ if (outBufLen > 0) {
+ /* copy what we can */
+ memcpy(outBuf, eventData, outBufLen);
+ outBuf += outBufLen;
+ outBufLen -= outBufLen;
+ }
+ if (!result) result = 1; /* if not truncated, return no room */
}
eventData += strLen;
eventDataLen -= strLen;
+ if (result != 0) goto bail;
break;
}
case EVENT_TYPE_LIST:
@@ -991,13 +997,16 @@
LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
struct logger_entry *buf,
AndroidLogEntry *entry,
- const EventTagMap *map __unused, // only on !__ANDROID__
+ const EventTagMap *map __unused, /* only on !__ANDROID__ */
char *messageBuf, int messageBufLen)
{
size_t inCount;
uint32_t tagIndex;
const unsigned char* eventData;
+ entry->message = NULL;
+ entry->messageLen = 0;
+
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
entry->priority = ANDROID_LOG_INFO;
@@ -1009,7 +1018,7 @@
* Pull the tag out, fill in some additional details based on incoming
* buffer version (v3 adds lid, v4 adds uid).
*/
- eventData = (const unsigned char*) buf->msg;
+ eventData = (const unsigned char*)buf->msg;
struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
if (buf2->hdr_size) {
if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
@@ -1122,7 +1131,7 @@
*/
*outBuf = '\0';
entry->messageLen = outBuf - messageBuf;
- assert(entry->messageLen == (messageBufLen-1) - outRemaining);
+ assert(entry->messageLen == (messageBufLen - 1) - outRemaining);
entry->message = messageBuf;
@@ -1217,7 +1226,7 @@
} else if (*message == '\b') {
strcpy(buf, "\\b");
} else if (*message == '\t') {
- strcpy(buf, "\t"); // Do not escape tabs
+ strcpy(buf, "\t"); /* Do not escape tabs */
} else if (*message == '\v') {
strcpy(buf, "\\v");
} else if (*message == '\f') {
@@ -1574,7 +1583,7 @@
nsec = entry->tv_nsec;
#if __ANDROID__
if (p_format->monotonic_output) {
- // prevent convertMonotonic from being called if logd is monotonic
+ /* prevent convertMonotonic from being called if logd is monotonic */
if (android_log_clockid() != CLOCK_MONOTONIC) {
struct timespec time;
convertMonotonic(&time, entry);
@@ -1648,7 +1657,7 @@
} else
#endif
{
- // Not worth parsing package list, names all longer than 5
+ /* Not worth parsing package list, names all longer than 5 */
snprintf(uid, sizeof(uid), "%5d:", entry->uid);
}
} else {
@@ -1758,7 +1767,7 @@
if (*pm++ == '\n') numLines++;
}
/* plus one line for anything not newline-terminated at the end */
- if (pm > entry->message && *(pm-1) != '\n') numLines++;
+ if (pm > entry->message && *(pm - 1) != '\n') numLines++;
}
/*
diff --git a/liblog/stderr_write.c b/liblog/stderr_write.c
new file mode 100644
index 0000000..b739299
--- /dev/null
+++ b/liblog/stderr_write.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*
+ * stderr write handler. Output is logcat-like, and responds to
+ * logcat's environment variables ANDROID_PRINTF_LOG and
+ * ANDROID_LOG_TAGS to filter output.
+ *
+ * This transport only provides a writer, that means that it does not
+ * provide an End-To-End capability as the logs are effectively _lost_
+ * to the stderr file stream. The purpose of this transport is to
+ * supply a means for command line tools to report their logging
+ * to the stderr stream, in line with all other activities.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <log/event_tag_map.h>
+#include <log/log.h>
+#include <log/logprint.h>
+#include <log/uio.h>
+
+#include "log_portability.h"
+#include "logger.h"
+
+static int stderrOpen();
+static void stderrClose();
+static int stderrAvailable(log_id_t logId);
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+ struct iovec* vec, size_t nr);
+
+struct stderrContext {
+ AndroidLogFormat* logformat;
+#if defined(__ANDROID__)
+ EventTagMap* eventTagMap;
+#endif
+};
+
+LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
+ .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
+ .context.private = NULL,
+ .name = "stderr",
+ .available = stderrAvailable,
+ .open = stderrOpen,
+ .close = stderrClose,
+ .write = stderrWrite,
+};
+
+static int stderrOpen()
+{
+ struct stderrContext* ctx;
+ const char* envStr;
+ bool setFormat;
+
+ if (!stderr || (fileno(stderr) < 0)) {
+ return -EBADF;
+ }
+
+ if (stderrLoggerWrite.context.private) {
+ return fileno(stderr);
+ }
+
+ ctx = calloc(1, sizeof(struct stderrContext));
+ if (!ctx) {
+ return -ENOMEM;
+ }
+
+ ctx->logformat = android_log_format_new();
+ if (!ctx->logformat) {
+ free(ctx);
+ return -ENOMEM;
+ }
+
+ envStr = getenv("ANDROID_PRINTF_LOG");
+ setFormat = false;
+
+ if (envStr) {
+ char* formats = strdup(envStr);
+ char* sv = NULL;
+ char* arg = formats;
+ while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
+ AndroidLogPrintFormat format = android_log_formatFromString(arg);
+ arg = NULL;
+ if (format == FORMAT_OFF) {
+ continue;
+ }
+ if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
+ continue;
+ }
+ setFormat = true;
+ }
+ free(formats);
+ }
+ if (!setFormat) {
+ AndroidLogPrintFormat format = android_log_formatFromString(
+ "threadtime");
+ android_log_setPrintFormat(ctx->logformat, format);
+ }
+ envStr = getenv("ANDROID_LOG_TAGS");
+ if (envStr) {
+ android_log_addFilterString(ctx->logformat, envStr);
+ }
+ stderrLoggerWrite.context.private = ctx;
+
+ return fileno(stderr);
+}
+
+static void stderrClose()
+{
+ struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+ if (ctx) {
+ stderrLoggerWrite.context.private = NULL;
+ if (ctx->logformat) {
+ android_log_format_free(ctx->logformat);
+ ctx->logformat = NULL;
+ }
+#if defined(__ANDROID__)
+ if (ctx->eventTagMap) {
+ android_closeEventTagMap(ctx->eventTagMap);
+ ctx->eventTagMap = NULL;
+ }
+#endif
+ }
+}
+
+static int stderrAvailable(log_id_t logId)
+{
+ if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
+ return -EINVAL;
+ }
+ return 1;
+}
+
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+ struct iovec* vec, size_t nr)
+{
+ struct log_msg log_msg;
+ AndroidLogEntry entry;
+ char binaryMsgBuf[1024];
+ int err;
+ size_t i;
+ struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+ if (!ctx) return -EBADF;
+ if (!vec || !nr) return -EINVAL;
+
+ log_msg.entry.len = 0;
+ log_msg.entry.hdr_size = sizeof(log_msg.entry);
+ log_msg.entry.pid = getpid();
+#ifdef __BIONIC__
+ log_msg.entry.tid = gettid();
+#else
+ log_msg.entry.tid = getpid();
+#endif
+ log_msg.entry.sec = ts->tv_sec;
+ log_msg.entry.nsec = ts->tv_nsec;
+ log_msg.entry.lid = logId;
+ log_msg.entry.uid = __android_log_uid();
+
+ for (i = 0; i < nr; ++i) {
+ size_t len = vec[i].iov_len;
+ if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
+ len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
+ }
+ if (!len) continue;
+ memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
+ log_msg.entry.len += len;
+ }
+
+ if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
+#if defined(__ANDROID__)
+ if (!ctx->eventTagMap) {
+ ctx->eventTagMap = android_openEventTagMap(NULL);
+ }
+#endif
+ err = android_log_processBinaryLogBuffer(&log_msg.entry_v1,
+ &entry,
+#if defined(__ANDROID__)
+ ctx->eventTagMap,
+#else
+ NULL,
+#endif
+ binaryMsgBuf,
+ sizeof(binaryMsgBuf));
+ } else {
+ err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
+ }
+
+ /* print known truncated data, in essence logcat --debug */
+ if ((err < 0) && !entry.message) return -EINVAL;
+
+ if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
+ return log_msg.entry.len;
+ }
+
+ err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
+ if (err < 0) return errno ? -errno : -EINVAL;
+ return log_msg.entry.len;
+}
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index cfea452..0e6432c 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -57,6 +57,8 @@
test_src_files := \
liblog_test_default.cpp \
liblog_test_local.cpp \
+ liblog_test_stderr.cpp \
+ liblog_test_stderr_local.cpp \
log_id_test.cpp \
log_radio_test.cpp \
log_read_test.cpp \
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index bc0ea4c..2537fac 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -47,7 +47,7 @@
#endif
#endif
-#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL))
+#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || !defined(USING_LOGGER_STDERR))
#ifdef liblog // a binary clue that we are overriding the test names
// Does not support log reading blocking feature yet
// Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD)
@@ -62,6 +62,11 @@
#define USING_LOGGER_DEFAULT
#endif
#endif
+#ifdef USING_LOGGER_STDERR
+# define SUPPORTS_END_TO_END 0
+#else
+# define SUPPORTS_END_TO_END 1
+#endif
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
// non-syscall libs. Since we are only using this in the emergency of
@@ -98,7 +103,7 @@
usleep(1000);
}
-#if (defined(__ANDROID__) && !defined(USING_LOGGER_LOCAL))
+#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT))
static std::string popenToString(std::string command) {
std::string ret;
@@ -176,8 +181,8 @@
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifndef USING_LOGGER_LOCAL
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+#ifdef USING_LOGGER_DEFAULT
// Check that we can close and reopen the logger
bool pmsgActiveAfter__android_log_btwrite;
bool logdwActiveAfter__android_log_btwrite;
@@ -200,8 +205,8 @@
#endif
log_time ts1(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifndef USING_LOGGER_LOCAL
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+#ifdef USING_LOGGER_DEFAULT
if (getuid() == AID_ROOT) {
pmsgActiveAfter__android_log_btwrite = isPmsgActive();
logdwActiveAfter__android_log_btwrite = isLogdwActive();
@@ -220,7 +225,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.len != sizeof(android_log_event_long_t))
|| (log_msg.id() != LOG_ID_EVENTS)) {
@@ -242,8 +247,8 @@
}
}
- EXPECT_EQ(1, count);
- EXPECT_EQ(1, second_count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, second_count);
android_logger_list_close(logger_list);
#else
@@ -251,6 +256,54 @@
#endif
}
+#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+static void print_frontend(const char* prefix, int logger) {
+ static const char orstr[] = " | ";
+
+ if (!prefix) {
+ prefix = "";
+ }
+ if (logger < 0) {
+ fprintf(stderr, "%s%s\n", prefix, strerror(-logger));
+ return;
+ }
+
+ if (logger == LOGGER_DEFAULT) {
+ fprintf(stderr, "%sLOGGER_DEFAULT", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_LOGD) {
+ fprintf(stderr, "%sLOGGER_LOGD", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_KERNEL) {
+ fprintf(stderr, "%sLOGGER_KERNEL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_NULL) {
+ fprintf(stderr, "%sLOGGER_NULL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_LOCAL) {
+ fprintf(stderr, "%sLOGGER_LOCAL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_STDERR) {
+ fprintf(stderr, "%sLOGGER_STDERR", prefix);
+ prefix = orstr;
+ }
+ logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL |
+ LOGGER_STDERR);
+ if (logger) {
+ fprintf(stderr, "%s0x%x", prefix, logger);
+ prefix = orstr;
+ }
+ if (prefix == orstr) {
+ fprintf(stderr, "\n");
+ }
+}
+#endif
+
// This test makes little sense standalone, and requires the tests ahead
// and behind us, to make us whole. We could incorporate a prefix and
// suffix test to make this standalone, but opted to not complicate this.
@@ -261,10 +314,14 @@
#endif
int logger = android_get_log_frontend();
+ print_frontend("android_get_log_frontend = ", logger);
EXPECT_NE(LOGGER_NULL, logger);
- EXPECT_EQ(LOGGER_NULL, android_set_log_frontend(LOGGER_NULL));
- EXPECT_EQ(LOGGER_NULL, android_get_log_frontend());
+ int ret;
+ EXPECT_EQ(LOGGER_NULL, ret = android_set_log_frontend(LOGGER_NULL));
+ print_frontend("android_set_log_frontend = ", ret);
+ EXPECT_EQ(LOGGER_NULL, ret = android_get_log_frontend());
+ print_frontend("android_get_log_frontend = ", ret);
pid_t pid = getpid();
@@ -273,7 +330,7 @@
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
usleep(1000000);
@@ -285,7 +342,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.len != sizeof(android_log_event_long_t))
|| (log_msg.id() != LOG_ID_EVENTS)) {
@@ -307,8 +364,10 @@
android_logger_list_close(logger_list);
- EXPECT_EQ(logger, android_set_log_frontend(logger));
- EXPECT_EQ(logger, android_get_log_frontend());
+ EXPECT_EQ(logger, ret = android_set_log_frontend(logger));
+ print_frontend("android_set_log_frontend = ", ret);
+ EXPECT_EQ(logger, ret = android_get_log_frontend());
+ print_frontend("android_get_log_frontend = ", ret);
// False negative if liblog.__android_log_btwrite__android_logger_list_read
// fails above, so we will likely succeed. But we will have so many
@@ -350,7 +409,7 @@
log_time ts(CLOCK_REALTIME);
#endif
- ASSERT_LT(0, __android_log_bswrite(0, message));
+ EXPECT_LT(0, __android_log_bswrite(0, message));
size_t num_lines = 1, size = 0, length = 0, total = 0;
const char *cp = message;
while (*cp) {
@@ -382,7 +441,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
@@ -413,19 +472,26 @@
int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
&log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
- if (processBinaryLogBuffer == 0) {
+ if ((processBinaryLogBuffer == 0) || entry.message) {
size_t line_overhead = 20;
if (pid > 99999) ++line_overhead;
if (pid > 999999) ++line_overhead;
fflush(stderr);
- EXPECT_EQ((int)((line_overhead * num_lines) + size),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
+ if (processBinaryLogBuffer) {
+ EXPECT_GT((int)((line_overhead * num_lines) + size),
+ android_log_printLogLine(logformat,
+ fileno(stderr), &entry));
+ } else {
+ EXPECT_EQ((int)((line_overhead * num_lines) + size),
+ android_log_printLogLine(logformat,
+ fileno(stderr), &entry));
+ }
}
android_log_format_free(logformat);
}
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -527,7 +593,7 @@
android_log_format_free(logformat);
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -1058,10 +1124,14 @@
android_logger_list_close(logger_list);
+#if SUPPORTS_END_TO_END
EXPECT_EQ(true, matches);
EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
#else
+ EXPECT_EQ(false, matches);
+#endif
+#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
@@ -1123,7 +1193,7 @@
android_log_format_free(logformat);
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -1184,6 +1254,11 @@
android_logger_list_close(logger_list);
+#if !SUPPORTS_END_TO_END
+ max_len = max_len ?
+ max_len :
+ LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag);
+#endif
EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
static_cast<size_t>(max_len));
@@ -1255,14 +1330,14 @@
android_logger_list_close(logger_list1);
android_logger_list_close(logger_list2);
- EXPECT_EQ(num, count1);
- EXPECT_EQ(num - 10, count2);
+ EXPECT_EQ(num * SUPPORTS_END_TO_END, count1);
+ EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#ifndef USING_LOGGER_LOCAL // Do not retest logprint
+#ifdef USING_LOGGER_DEFAULT // Do not retest logprint
static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) {
return android_log_shouldPrintLine(p_format, tag, pri)
&& !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1));
@@ -1331,9 +1406,9 @@
android_log_format_free(p_format);
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest property handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest property handling
TEST(liblog, is_loggable) {
#ifdef __ANDROID__
static const char tag[] = "is_loggable";
@@ -1632,12 +1707,12 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
// Following tests the specific issues surrounding error handling wrt logd.
// Kills logd and toss all collected data, equivalent to logcat -b all -c,
// except we also return errors to the logging callers.
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
// helper to liblog.enoent to count end-to-end matching logging messages.
static int count_matching_ts(log_time ts) {
@@ -1687,7 +1762,7 @@
TEST_PREFIX
log_time ts(CLOCK_MONOTONIC);
EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
- EXPECT_EQ(1, count_matching_ts(ts));
+ EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
// This call will fail if we are setuid(AID_SYSTEM), beware of any
// test prior to this one playing with setuid and causing interference.
@@ -1732,18 +1807,18 @@
ts = log_time(CLOCK_MONOTONIC);
EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
- EXPECT_EQ(1, count_matching_ts(ts));
+ EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOCAL_LOGGER
+#endif // USING_LOCAL_LOGD
// Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
// Do not retest properties, and cannot log into LOG_ID_SECURITY
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
TEST(liblog, __security) {
#ifdef __ANDROID__
static const char persist_key[] = "persist.logd.security";
@@ -1929,7 +2004,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
@@ -2047,7 +2122,7 @@
max_payload_buf,
200,
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2063,7 +2138,7 @@
max_payload_buf,
sizeof(max_payload_buf),
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2095,7 +2170,7 @@
max_payload_buf,
200,
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2118,6 +2193,46 @@
count = 0;
+ // Do a Before and After on the count to measure the effect. Decrement
+ // what we find in Before to set the stage.
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
+
+ char *eventData = log_msg.msg();
+ if (!eventData) continue;
+
+ // Tag
+ int tag = get4LE(eventData);
+ eventData += 4;
+
+ if (tag != TAG) continue;
+
+ if (!SUBTAG) {
+ // This tag should not have been written because the data was null
+ --count;
+ break;
+ }
+
+ // List type
+ eventData++;
+ // Number of elements in list
+ eventData++;
+ // Element #1: string type for subtag
+ eventData++;
+
+ eventData +=4;
+
+ if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
+ --count;
+ }
+
+ android_logger_list_close(logger_list);
+
+ // Do an After on the count to measure the effect.
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
@@ -2184,7 +2299,7 @@
#ifdef TEST_PREFIX
int count;
android_errorWriteLog_helper(123456785, "test-subtag", count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2703,7 +2818,7 @@
EXPECT_EQ(0, strcmp(expected_string, msgBuf));
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
}
@@ -2789,7 +2904,7 @@
#endif
}
-#ifndef USING_LOGGER_LOCAL // Do not retest logger list handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest logger list handling
TEST(liblog, create_android_logger_overflow) {
android_log_context ctx;
@@ -2829,9 +2944,9 @@
msgBuf, sizeof(msgBuf)), 0);
EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest pmsg functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest pmsg functionality
#ifdef __ANDROID__
static const char __pmsg_file[] =
"/data/william-shakespeare/MuchAdoAboutNothing.txt";
@@ -2957,9 +3072,9 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
#ifdef __ANDROID__
// must be: '<needle:> 0 kB'
static bool isZero(const std::string &content, std::string::size_type pos,
@@ -3063,9 +3178,9 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest ratelimit
+#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit
TEST(liblog, __android_log_ratelimit) {
time_t state = 0;
@@ -3097,9 +3212,9 @@
}
// Do not test default seconds, to allow liblog to tune freely
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
EventTagMap* map = android_openEventTagMap(NULL);
@@ -3115,4 +3230,4 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
new file mode 100644
index 0000000..f0cb192
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr.cpp
@@ -0,0 +1,5 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr
+#define TEST_PREFIX android_set_log_frontend(LOGGER_STDERR);
+#define USING_LOGGER_STDERR
+#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
new file mode 100644
index 0000000..1555b4e
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr_local.cpp
@@ -0,0 +1,4 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr_local
+#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL | LOGGER_STDERR);
+#include "liblog_test.cpp"
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 75eab66..da8afe1 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -22,7 +22,7 @@
// 524291 corresponds to sysui_histogram, from
// frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
- "-DHISTOGRAM_LOG_TAG=524291",
+ "-DHISTOGRAM_LOG_TAG=524292",
],
}
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index d30e56c..26aa189 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,5 +24,14 @@
// buffer.
void LogHistogram(const std::string& event, int32_t data);
+// TODO: replace these with the metric_logger.proto definitions
+enum {
+ LOGBUILDER_CATEGORY = 757,
+ LOGBUILDER_NAME = 799,
+ LOGBUILDER_BUCKET = 801,
+ LOGBUILDER_VALUE = 802,
+ LOGBUILDER_HISTOGRAM = 804,
+};
+
} // namespace metricslogger
} // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index f8e0174..0d08f5c 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,14 @@
namespace android {
namespace metricslogger {
+// Mirror com.android.internal.logging.MetricsLogger#histogram().
void LogHistogram(const std::string& event, int32_t data) {
android_log_event_list log(HISTOGRAM_LOG_TAG);
- log << event << data << LOG_ID_EVENTS;
+ log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM
+ << LOGBUILDER_NAME << event
+ << LOGBUILDER_BUCKET << data
+ << LOGBUILDER_VALUE << 1
+ << LOG_ID_EVENTS;
}
} // namespace metricslogger
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
index 126995b..b0fdd44 100644
--- a/libutils/BlobCache.cpp
+++ b/libutils/BlobCache.cpp
@@ -17,13 +17,10 @@
#define LOG_TAG "BlobCache"
//#define LOG_NDEBUG 0
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
#include <utils/BlobCache.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
+#include <utils/Timers.h>
+
+#include <inttypes.h>
#include <cutils/properties.h>
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index 699da74..bd6015e 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "CallStack"
+#include <utils/CallStack.h>
+
#include <memory>
-#include <utils/CallStack.h>
#include <utils/Printer.h>
#include <utils/Errors.h>
#include <utils/Log.h>
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
index 138ce8b..d2e91a8 100644
--- a/libutils/LinearTransform.cpp
+++ b/libutils/LinearTransform.cpp
@@ -16,10 +16,9 @@
#define __STDC_LIMIT_MACROS
-#include <assert.h>
-#include <stdint.h>
-
#include <utils/LinearTransform.h>
+#include <assert.h>
+
// disable sanitize as these functions may intentionally overflow (see comments below).
// the ifdef can be removed when host builds use clang.
diff --git a/libutils/Log.cpp b/libutils/Log.cpp
index bffb56e..2c1fb86 100644
--- a/libutils/Log.cpp
+++ b/libutils/Log.cpp
@@ -21,14 +21,14 @@
namespace android {
-LogIfSlow::LogIfSlow(const char* tag, android_LogPriority priority,
- int timeoutMillis, const char* message) :
- mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message),
- mStart(systemTime(SYSTEM_TIME_BOOTTIME)) {
+LogIfSlow::LogIfSlow(
+ const char* tag, android_LogPriority priority, int timeoutMillis, const char* message)
+ : mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message),
+ mStart(systemTime(SYSTEM_TIME_BOOTTIME)) {
}
LogIfSlow::~LogIfSlow() {
- int durationMillis = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart);
+ int durationMillis = (int)nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart);
if (durationMillis > mTimeoutMillis) {
LOG_PRI(mPriority, mTag, "%s: %dms", mMessage, durationMillis);
}
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 84bc028..6c57b2e 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -13,17 +13,8 @@
// Debugs callback registration and invocation.
#define DEBUG_CALLBACKS 0
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include <log/log.h>
#include <utils/Looper.h>
-#include <utils/Timers.h>
+#include <sys/eventfd.h>
namespace android {
diff --git a/libutils/NativeHandle.cpp b/libutils/NativeHandle.cpp
index e4daca7..97d06b8 100644
--- a/libutils/NativeHandle.cpp
+++ b/libutils/NativeHandle.cpp
@@ -19,14 +19,14 @@
namespace android {
-sp<NativeHandle> NativeHandle::create(
- native_handle_t* handle, bool ownsHandle) {
+sp<NativeHandle> NativeHandle::create(native_handle_t* handle, bool ownsHandle) {
return handle ? new NativeHandle(handle, ownsHandle) : NULL;
}
NativeHandle::NativeHandle(native_handle_t* handle, bool ownsHandle)
-: mHandle(handle), mOwnsHandle(ownsHandle)
-{}
+ : mHandle(handle), mOwnsHandle(ownsHandle) {
+
+}
NativeHandle::~NativeHandle() {
if (mOwnsHandle) {
diff --git a/libutils/Printer.cpp b/libutils/Printer.cpp
index 98cd2c6..9573a10 100644
--- a/libutils/Printer.cpp
+++ b/libutils/Printer.cpp
@@ -21,10 +21,6 @@
#include <utils/String8.h>
#include <utils/Log.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
namespace android {
/*
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index 73ed4eb..1d9f30d 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -17,18 +17,11 @@
#define LOG_TAG "ProcessCallStack"
// #define LOG_NDEBUG 0
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <memory>
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
#include <utils/ProcessCallStack.h>
-#include <utils/Printer.h>
-#include <limits.h>
+#include <dirent.h>
+
+#include <utils/Printer.h>
namespace android {
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index 5520702..4bcdd0f 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -16,11 +16,7 @@
#define LOG_TAG "PropertyMap"
-#include <stdlib.h>
-#include <string.h>
-
#include <utils/PropertyMap.h>
-#include <utils/Log.h>
// Enables debug output for the parser.
#define DEBUG_PARSER 0
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 4252ba6..0d98db9 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -17,18 +17,9 @@
#define LOG_TAG "RefBase"
// #define LOG_NDEBUG 0
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
#include <utils/RefBase.h>
#include <utils/CallStack.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
#ifndef __unused
#define __unused __attribute__((__unused__))
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 1fa1d7a..bad98b2 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "sharedbuffer"
+#include "SharedBuffer.h"
+
#include <stdlib.h>
#include <string.h>
#include <log/log.h>
-#include "SharedBuffer.h"
-
// ---------------------------------------------------------------------------
namespace android {
diff --git a/libutils/StopWatch.cpp b/libutils/StopWatch.cpp
index 8c7b596..219c13c 100644
--- a/libutils/StopWatch.cpp
+++ b/libutils/StopWatch.cpp
@@ -16,9 +16,7 @@
#define LOG_TAG "StopWatch"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <utils/StopWatch.h>
/* for PRId64 */
#ifndef __STDC_FORMAT_MACROS
@@ -27,8 +25,6 @@
#include <inttypes.h>
#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/StopWatch.h>
/*****************************************************************************/
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 9f5cfea..12bb7c4 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -17,12 +17,6 @@
#include <utils/String16.h>
#include <utils/Log.h>
-#include <utils/Unicode.h>
-#include <utils/threads.h>
-
-#include <memory.h>
-#include <stdio.h>
-#include <ctype.h>
#include "SharedBuffer.h"
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index cacaf91..0ac39f9 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -21,11 +21,7 @@
#include <utils/Compat.h>
#include <utils/Log.h>
-#include <utils/Unicode.h>
#include <utils/String16.h>
-#include <utils/threads.h>
-
-#include <ctype.h>
#include "SharedBuffer.h"
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 965e32c..28fc351 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -19,17 +19,17 @@
* System clock functions.
*/
+#define LOG_TAG "SystemClock"
+
+#include <utils/SystemClock.h>
+
#include <sys/time.h>
-#include <limits.h>
-#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <cutils/compiler.h>
-#include <utils/SystemClock.h>
-#include <utils/Timers.h>
-#define LOG_TAG "SystemClock"
+#include <utils/Timers.h>
#include <utils/Log.h>
namespace android {
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index def739f..6317c32 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -18,16 +18,10 @@
#define LOG_TAG "libutils.threads"
#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <utils/Thread.h>
+#include <utils/AndroidThreads.h>
#if !defined(_WIN32)
-# include <pthread.h>
-# include <sched.h>
# include <sys/resource.h>
#else
# include <windows.h>
@@ -40,7 +34,6 @@
#include <sys/prctl.h>
#endif
-#include <utils/threads.h>
#include <utils/Log.h>
#include <cutils/sched_policy.h>
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index 201bc41..b2df9a5 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -20,7 +20,6 @@
#include <utils/Timers.h>
#include <limits.h>
-#include <sys/time.h>
#include <time.h>
#if defined(__ANDROID__)
@@ -53,7 +52,7 @@
int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
{
- int timeoutDelayMillis;
+ nsecs_t timeoutDelayMillis;
if (timeoutTime > referenceTime) {
uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
@@ -64,5 +63,5 @@
} else {
timeoutDelayMillis = 0;
}
- return timeoutDelayMillis;
+ return (int)timeoutDelayMillis;
}
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index 2d0e83d..b68a2cf 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -16,14 +16,10 @@
#define LOG_TAG "Tokenizer"
-#include <stdlib.h>
-#include <unistd.h>
+#include <utils/Tokenizer.h>
#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <utils/Log.h>
-#include <utils/Tokenizer.h>
// Enables debug output for the tokenizer.
#define DEBUG_TOKENIZER 0
diff --git a/libutils/Trace.cpp b/libutils/Trace.cpp
index 36fd802..8530fdc 100644
--- a/libutils/Trace.cpp
+++ b/libutils/Trace.cpp
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#include <utils/misc.h>
#include <utils/Trace.h>
+#include <utils/misc.h>
static void traceInit() __attribute__((constructor));
-static void traceInit()
-{
+static void traceInit() {
::android::add_sysprop_change_callback(atrace_update_tags, 0);
}
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index f1a41b9..5fd9155 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -16,11 +16,10 @@
#define LOG_TAG "unicode"
+#include <utils/Unicode.h>
#include <limits.h>
-#include <stddef.h>
#include <log/log.h>
-#include <utils/Unicode.h>
#if defined(_WIN32)
# undef nhtol
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index f7ca8f4..ef3277f 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "Vector"
+#include <utils/VectorImpl.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/VectorImpl.h>
#include <safe_iop.h>
diff --git a/libutils/include/utils/BlobCache.h b/libutils/include/utils/BlobCache.h
index 65dca9f..27a81e3 100644
--- a/libutils/include/utils/BlobCache.h
+++ b/libutils/include/utils/BlobCache.h
@@ -19,10 +19,8 @@
#include <stddef.h>
-#include <utils/Flattenable.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
-#include <utils/threads.h>
namespace android {
diff --git a/libutils/include/utils/Condition.h b/libutils/include/utils/Condition.h
index 2c80acd..3019a21 100644
--- a/libutils/include/utils/Condition.h
+++ b/libutils/include/utils/Condition.h
@@ -41,6 +41,11 @@
* call wait(), then either re-wait() if things aren't quite what you want,
* or unlock the mutex and continue. All threads calling wait() must
* use the same mutex for a given Condition.
+ *
+ * On Android and Apple platforms, these are implemented as a simple wrapper
+ * around pthread condition variables. Care must be taken to abide by
+ * the pthreads semantics, in particular, a boolean predicate must
+ * be re-evaluated after a wake-up, as spurious wake-ups may happen.
*/
class Condition {
public:
@@ -58,10 +63,11 @@
explicit Condition(int type);
~Condition();
// Wait on the condition variable. Lock the mutex before calling.
+ // Note that spurious wake-ups may happen.
status_t wait(Mutex& mutex);
// same with relative timeout
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
- // Signal the condition variable, allowing exactly one thread to continue.
+ // Signal the condition variable, allowing one thread to continue.
void signal();
// Signal the condition variable, allowing one or all threads to continue.
void signal(WakeUpType type) {
@@ -142,17 +148,6 @@
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
}
inline void Condition::signal() {
- /*
- * POSIX says pthread_cond_signal wakes up "one or more" waiting threads.
- * However bionic follows the glibc guarantee which wakes up "exactly one"
- * waiting thread.
- *
- * man 3 pthread_cond_signal
- * pthread_cond_signal restarts one of the threads that are waiting on
- * the condition variable cond. If no threads are waiting on cond,
- * nothing happens. If several threads are waiting on cond, exactly one
- * is restarted, but it is not specified which.
- */
pthread_cond_signal(&mCond);
}
inline void Condition::broadcast() {
diff --git a/libutils/include/utils/NativeHandle.h b/libutils/include/utils/NativeHandle.h
index b825168..73fe804 100644
--- a/libutils/include/utils/NativeHandle.h
+++ b/libutils/include/utils/NativeHandle.h
@@ -24,7 +24,7 @@
namespace android {
-class NativeHandle: public LightRefBase<NativeHandle> {
+class NativeHandle : public LightRefBase<NativeHandle> {
public:
// Create a refcounted wrapper around a native_handle_t, and declare
// whether the wrapper owns the handle (so that it should clean up the
@@ -41,7 +41,7 @@
friend class LightRefBase<NativeHandle>;
NativeHandle(native_handle_t* handle, bool ownsHandle);
- virtual ~NativeHandle();
+ ~NativeHandle();
native_handle_t* mHandle;
bool mOwnsHandle;
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 36016cd..a61ea58 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -371,10 +371,8 @@
private:
friend class ReferenceMover;
- inline static void renameRefs(size_t /*n*/,
- const ReferenceRenamer& /*renamer*/) { }
- inline static void renameRefId(T* /*ref*/,
- const void* /*old_id*/ , const void* /*new_id*/) { }
+ inline static void renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { }
+ inline static void renameRefId(T* /*ref*/, const void* /*old_id*/ , const void* /*new_id*/) { }
private:
mutable std::atomic<int32_t> mCount;
diff --git a/libutils/include/utils/Singleton.h b/libutils/include/utils/Singleton.h
index a989a47..bdb2332 100644
--- a/libutils/include/utils/Singleton.h
+++ b/libutils/include/utils/Singleton.h
@@ -18,9 +18,12 @@
#define ANDROID_UTILS_SINGLETON_H
#include <stdint.h>
+
+// some vendor code assumes they have atoi() after including this file.
+#include <stdlib.h>
+
#include <sys/types.h>
#include <utils/Mutex.h>
-#include <utils/threads.h>
#include <cutils/compiler.h>
namespace android {
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 294e6b6..cdfdd8a 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,12 +17,6 @@
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
-#include <cutils/atomic.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <stdlib.h>
-
// ---------------------------------------------------------------------------
namespace android {
diff --git a/libutils/include/utils/Trace.h b/libutils/include/utils/Trace.h
index eeba40d..5e9229c 100644
--- a/libutils/include/utils/Trace.h
+++ b/libutils/include/utils/Trace.h
@@ -19,16 +19,8 @@
#if defined(__ANDROID__)
-#include <fcntl.h>
#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <cutils/compiler.h>
-#include <utils/threads.h>
#include <cutils/trace.h>
// See <cutils/trace.h> for more ATRACE_* macros.
@@ -37,6 +29,7 @@
#define _PASTE(x, y) x ## y
#define PASTE(x, y) _PASTE(x,y)
#define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+
// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
@@ -44,14 +37,13 @@
class ScopedTrace {
public:
-inline ScopedTrace(uint64_t tag, const char* name)
- : mTag(tag) {
- atrace_begin(mTag,name);
-}
+ inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
+ atrace_begin(mTag, name);
+ }
-inline ~ScopedTrace() {
- atrace_end(mTag);
-}
+ inline ~ScopedTrace() {
+ atrace_end(mTag);
+ }
private:
uint64_t mTag;
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
index 216dc14..2608a65 100644
--- a/libutils/misc.cpp
+++ b/libutils/misc.cpp
@@ -22,12 +22,7 @@
#include <utils/misc.h>
#include <utils/Log.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
-
#if !defined(_WIN32)
-# include <pthread.h>
#endif
#include <utils/Vector.h>
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 723c35e..f564f0f 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -16,7 +16,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := liblogcat
-LOCAL_SRC_FILES := logcat.cpp logcat_system.cpp
+LOCAL_SRC_FILES := logcat.cpp getopt_long.cpp logcat_system.cpp
LOCAL_SHARED_LIBRARIES := $(logcatLibs)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/logcat/getopt_long.cpp b/logcat/getopt_long.cpp
new file mode 100644
index 0000000..5f8dd66
--- /dev/null
+++ b/logcat/getopt_long.cpp
@@ -0,0 +1,402 @@
+/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cdefs.h>
+
+#include <log/getopt.h>
+
+#define PRINT_ERROR ((context->opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01 // permute non-options to the end of argv
+#define FLAG_ALLARGS 0x02 // treat non-options as args to option "-1"
+
+// return values
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define D_PREFIX 0
+#define DD_PREFIX 1
+#define W_PREFIX 2
+
+// Compute the greatest common divisor of a and b.
+static int gcd(int a, int b) {
+ int c = a % b;
+ while (c) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+ return b;
+}
+
+// Exchange the block from nonopt_start to nonopt_end with the block from
+// nonopt_end to opt_end (keeping the same order of arguments in each block).
+// Returns optind - (nonopt_end - nonopt_start) for convenience.
+static int permute_args(getopt_context* context, char* const* nargv) {
+ // compute lengths of blocks and number and size of cycles
+ int nnonopts = context->nonopt_end - context->nonopt_start;
+ int nopts = context->optind - context->nonopt_end;
+ int ncycle = gcd(nnonopts, nopts);
+ int cyclelen = (context->optind - context->nonopt_start) / ncycle;
+
+ for (int i = 0; i < ncycle; i++) {
+ int cstart = context->nonopt_end + i;
+ int pos = cstart;
+ for (int j = 0; j < cyclelen; j++) {
+ if (pos >= context->nonopt_end) {
+ pos -= nnonopts;
+ } else {
+ pos += nopts;
+ }
+ char* swap = nargv[pos];
+ const_cast<char**>(nargv)[pos] = nargv[cstart];
+ const_cast<char**>(nargv)[cstart] = swap;
+ }
+ }
+ return context->optind - (context->nonopt_end - context->nonopt_start);
+}
+
+// parse_long_options_r --
+// Parse long options in argc/argv argument vector.
+// Returns -1 if short_too is set and the option does not match long_options.
+static int parse_long_options_r(char* const* nargv, const char* options,
+ const struct option* long_options, int* idx,
+ bool short_too, struct getopt_context* context) {
+ const char* current_argv = context->place;
+ const char* current_dash;
+ switch (context->dash_prefix) {
+ case D_PREFIX:
+ current_dash = "-";
+ break;
+ case DD_PREFIX:
+ current_dash = "--";
+ break;
+ case W_PREFIX:
+ current_dash = "-W ";
+ break;
+ default:
+ current_dash = "";
+ break;
+ }
+ context->optind++;
+
+ const char* has_equal;
+ size_t current_argv_len;
+ if (!!(has_equal = strchr(current_argv, '='))) {
+ // argument found (--option=arg)
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else {
+ current_argv_len = strlen(current_argv);
+ }
+
+ int match = -1;
+ bool exact_match = false;
+ bool second_partial_match = false;
+ for (int i = 0; long_options[i].name; i++) {
+ // find matching long option
+ if (strncmp(current_argv, long_options[i].name, current_argv_len)) {
+ continue;
+ }
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ // exact match
+ match = i;
+ exact_match = true;
+ break;
+ }
+ // If this is a known short option, don't allow
+ // a partial match of a single character.
+ if (short_too && current_argv_len == 1) continue;
+
+ if (match == -1) { // first partial match
+ match = i;
+ } else if (long_options[i].has_arg != long_options[match].has_arg ||
+ long_options[i].flag != long_options[match].flag ||
+ long_options[i].val != long_options[match].val) {
+ second_partial_match = true;
+ }
+ }
+ if (!exact_match && second_partial_match) {
+ // ambiguous abbreviation
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr,
+ "option `%s%.*s' is ambiguous", current_dash,
+ (int)current_argv_len, current_argv);
+ }
+ context->optopt = 0;
+ return BADCH;
+ }
+ if (match != -1) { // option found
+ if (long_options[match].has_arg == no_argument && has_equal) {
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr,
+ "option `%s%.*s' doesn't allow an argument",
+ current_dash, (int)current_argv_len, current_argv);
+ }
+ // XXX: GNU sets optopt to val regardless of flag
+ context->optopt =
+ long_options[match].flag ? 0 : long_options[match].val;
+ return BADCH;
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal) {
+ context->optarg = has_equal;
+ } else if (long_options[match].has_arg == required_argument) {
+ // optional argument doesn't use next nargv
+ context->optarg = nargv[context->optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument) &&
+ !context->optarg) {
+ // Missing argument; leading ':' indicates no error
+ // should be generated.
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr,
+ "option `%s%s' requires an argument", current_dash,
+ current_argv);
+ }
+ // XXX: GNU sets optopt to val regardless of flag
+ context->optopt =
+ long_options[match].flag ? 0 : long_options[match].val;
+ context->optind--;
+ return BADARG;
+ }
+ } else { // unknown option
+ if (short_too) {
+ context->optind--;
+ return -1;
+ }
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr, "unrecognized option `%s%s'",
+ current_dash, current_argv);
+ }
+ context->optopt = 0;
+ return BADCH;
+ }
+ if (idx) *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return 0;
+ }
+ return long_options[match].val;
+}
+
+// getopt_long_r --
+// Parse argc/argv argument vector.
+int getopt_long_r(int nargc, char* const* nargv, const char* options,
+ const struct option* long_options, int* idx,
+ struct getopt_context* context) {
+ if (!options) return -1;
+
+ // XXX Some GNU programs (like cvs) set optind to 0 instead of
+ // XXX using optreset. Work around this braindamage.
+ if (!context->optind) context->optind = context->optreset = 1;
+
+ // Disable GNU extensions if options string begins with a '+'.
+ int flags = FLAG_PERMUTE;
+ if (*options == '-') {
+ flags |= FLAG_ALLARGS;
+ } else if (*options == '+') {
+ flags &= ~FLAG_PERMUTE;
+ }
+ if (*options == '+' || *options == '-') options++;
+
+ context->optarg = nullptr;
+ if (context->optreset) context->nonopt_start = context->nonopt_end = -1;
+start:
+ if (context->optreset || !*context->place) { // update scanning pointer
+ context->optreset = 0;
+ if (context->optind >= nargc) { // end of argument vector
+ context->place = EMSG;
+ if (context->nonopt_end != -1) {
+ // do permutation, if we have to
+ context->optind = permute_args(context, nargv);
+ } else if (context->nonopt_start != -1) {
+ // If we skipped non-options, set optind to the first of them.
+ context->optind = context->nonopt_start;
+ }
+ context->nonopt_start = context->nonopt_end = -1;
+ return -1;
+ }
+ if (*(context->place = nargv[context->optind]) != '-' ||
+ context->place[1] == '\0') {
+ context->place = EMSG; // found non-option
+ if (flags & FLAG_ALLARGS) {
+ // GNU extension: return non-option as argument to option 1
+ context->optarg = nargv[context->optind++];
+ return INORDER;
+ }
+ if (!(flags & FLAG_PERMUTE)) {
+ // If no permutation wanted, stop parsing at first non-option.
+ return -1;
+ }
+ // do permutation
+ if (context->nonopt_start == -1) {
+ context->nonopt_start = context->optind;
+ } else if (context->nonopt_end != -1) {
+ context->nonopt_start = permute_args(context, nargv);
+ context->nonopt_end = -1;
+ }
+ context->optind++;
+ // process next argument
+ goto start;
+ }
+ if (context->nonopt_start != -1 && context->nonopt_end == -1) {
+ context->nonopt_end = context->optind;
+ }
+
+ // If we have "-" do nothing, if "--" we are done.
+ if (context->place[1] != '\0' && *++(context->place) == '-' &&
+ context->place[1] == '\0') {
+ context->optind++;
+ context->place = EMSG;
+ // We found an option (--), so if we skipped
+ // non-options, we have to permute.
+ if (context->nonopt_end != -1) {
+ context->optind = permute_args(context, nargv);
+ }
+ context->nonopt_start = context->nonopt_end = -1;
+ return -1;
+ }
+ }
+
+ int optchar;
+ // Check long options if:
+ // 1) we were passed some
+ // 2) the arg is not just "-"
+ // 3) either the arg starts with -- we are getopt_long_only()
+ if (long_options && context->place != nargv[context->optind] &&
+ (*context->place == '-')) {
+ bool short_too = false;
+ context->dash_prefix = D_PREFIX;
+ if (*context->place == '-') {
+ context->place++; // --foo long option
+ context->dash_prefix = DD_PREFIX;
+ } else if (*context->place != ':' && strchr(options, *context->place)) {
+ short_too = true; // could be short option too
+ }
+
+ optchar = parse_long_options_r(nargv, options, long_options, idx,
+ short_too, context);
+ if (optchar != -1) {
+ context->place = EMSG;
+ return optchar;
+ }
+ }
+
+ const char* oli; // option letter list index
+ if ((optchar = (int)*(context->place)++) == (int)':' ||
+ (optchar == (int)'-' && *context->place != '\0') ||
+ !(oli = strchr(options, optchar))) {
+ // If the user specified "-" and '-' isn't listed in
+ // options, return -1 (non-option) as per POSIX.
+ // Otherwise, it is an unknown option character (or ':').
+ if (optchar == (int)'-' && *context->place == '\0') return -1;
+ if (!*context->place) context->optind++;
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr, "invalid option -- %c",
+ optchar);
+ }
+ context->optopt = optchar;
+ return BADCH;
+ }
+
+ static const char recargchar[] = "option requires an argument -- %c";
+ if (long_options && optchar == 'W' && oli[1] == ';') {
+ // -W long-option
+ if (*context->place) { // no space
+ ; // NOTHING
+ } else if (++(context->optind) >= nargc) { // no arg
+ context->place = EMSG;
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr, recargchar, optchar);
+ }
+ context->optopt = optchar;
+ return BADARG;
+ } else { // white space
+ context->place = nargv[context->optind];
+ }
+ context->dash_prefix = W_PREFIX;
+ optchar = parse_long_options_r(nargv, options, long_options, idx, false,
+ context);
+ context->place = EMSG;
+ return optchar;
+ }
+ if (*++oli != ':') { // doesn't take argument
+ if (!*context->place) context->optind++;
+ } else { // takes (optional) argument
+ context->optarg = nullptr;
+ if (*context->place) { // no white space
+ context->optarg = context->place;
+ } else if (oli[1] != ':') { // arg not optional
+ if (++(context->optind) >= nargc) { // no arg
+ context->place = EMSG;
+ if (PRINT_ERROR) {
+ fprintf(context->optstderr ?: stderr, recargchar, optchar);
+ }
+ context->optopt = optchar;
+ return BADARG;
+ }
+ context->optarg = nargv[context->optind];
+ }
+ context->place = EMSG;
+ context->optind++;
+ }
+ // dump back option letter
+ return optchar;
+}
diff --git a/logcat/include/log/getopt.h b/logcat/include/log/getopt.h
new file mode 100644
index 0000000..0da2b10
--- /dev/null
+++ b/logcat/include/log/getopt.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef _LOG_GETOPT_H_
+#define _LOG_GETOPT_H_
+
+#ifndef __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
+#ifndef __ANDROID_API__
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
+#elif __ANDROID_API__ > 24 /* > Nougat */
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
+#else
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 0
+#endif
+#endif
+
+#if __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
+
+#include <getopt.h>
+#include <sys/cdefs.h>
+
+struct getopt_context {
+ int opterr;
+ int optind;
+ int optopt;
+ int optreset;
+ const char* optarg;
+ FILE* optstderr; /* NULL defaults to stderr */
+ /* private */
+ const char* place;
+ int nonopt_start;
+ int nonopt_end;
+ int dash_prefix;
+ /* expansion space */
+ int __extra__;
+ void* __stuff__;
+};
+
+#define EMSG ""
+#define NO_PREFIX (-1)
+
+#define INIT_GETOPT_CONTEXT(context) \
+ context = { 1, 1, '?', 0, NULL, NULL, EMSG, -1, -1, NO_PREFIX, 0, NULL }
+
+__BEGIN_DECLS
+int getopt_long_r(int nargc, char* const* nargv, const char* options,
+ const struct option* long_options, int* idx,
+ struct getopt_context* context);
+
+__END_DECLS
+
+#endif /* __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE */
+
+#endif /* !_LOG_GETOPT_H_ */
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 077332a..4da5030 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -20,7 +20,6 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <getopt.h>
#include <math.h>
#include <pthread.h>
#include <sched.h>
@@ -47,6 +46,7 @@
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
+#include <log/getopt.h>
#include <log/logcat.h>
#include <log/logprint.h>
#include <private/android_logger.h>
@@ -56,6 +56,25 @@
#define DEFAULT_MAX_ROTATED_LOGS 4
+struct log_device_t {
+ const char* device;
+ bool binary;
+ struct logger* logger;
+ struct logger_list* logger_list;
+ bool printed;
+
+ log_device_t* next;
+
+ log_device_t(const char* d, bool b) {
+ device = d;
+ binary = b;
+ next = nullptr;
+ printed = false;
+ logger = nullptr;
+ logger_list = nullptr;
+ }
+};
+
struct android_logcat_context_internal {
// status
volatile std::atomic_int retval; // valid if thread_stopped set
@@ -91,15 +110,15 @@
int printBinary;
int devCount; // >1 means multiple
pcrecpp::RE* regex;
+ log_device_t* devices;
+ EventTagMap* eventTagMap;
// 0 means "infinite"
size_t maxCount;
size_t printCount;
+
bool printItAnyways;
bool debug;
-
- // static variables
bool hasOpenedEventTagMap;
- EventTagMap* eventTagMap;
};
// Creates a context associated with this logcat instance
@@ -127,25 +146,6 @@
// logd prefixes records with a length field
#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
-struct log_device_t {
- const char* device;
- bool binary;
- struct logger* logger;
- struct logger_list* logger_list;
- bool printed;
-
- log_device_t* next;
-
- log_device_t(const char* d, bool b) {
- device = d;
- binary = b;
- next = nullptr;
- printed = false;
- logger = nullptr;
- logger_list = nullptr;
- }
-};
-
namespace android {
enum helpType { HELP_FALSE, HELP_TRUE, HELP_FORMAT };
@@ -635,19 +635,17 @@
}
// Find last logged line in <outputFileName>, or <outputFileName>.1
-static log_time lastLogTime(char* outputFileName) {
+static log_time lastLogTime(const char* outputFileName) {
log_time retval(log_time::EPOCH);
if (!outputFileName) return retval;
std::string directory;
- char* file = strrchr(outputFileName, '/');
+ const char* file = strrchr(outputFileName, '/');
if (!file) {
directory = ".";
file = outputFileName;
} else {
- *file = '\0';
- directory = outputFileName;
- *file = '/';
+ directory = std::string(outputFileName, file - outputFileName);
++file;
}
@@ -736,11 +734,10 @@
bool printStatistics = false;
bool printDividers = false;
unsigned long setLogSize = 0;
- char* setPruneList = nullptr;
- char* setId = nullptr;
+ const char* setPruneList = nullptr;
+ const char* setId = nullptr;
int mode = ANDROID_LOG_RDONLY;
std::string forceFilters;
- log_device_t* devices = nullptr;
log_device_t* dev;
struct logger_list* logger_list;
size_t tail_lines = 0;
@@ -855,8 +852,11 @@
// net for stability dealing with possible mistaken inputs.
static const char delimiters[] = ",:; \t\n\r\f";
- // danger: getopt is _not_ reentrant
- optind = 1;
+ struct getopt_context optctx;
+ INIT_GETOPT_CONTEXT(optctx);
+ optctx.opterr = !!context->error;
+ optctx.optstderr = context->error;
+
for (;;) {
int ret;
@@ -899,9 +899,9 @@
};
// clang-format on
- ret = getopt_long(argc, argv,
- ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
- &option_index);
+ ret = getopt_long_r(argc, argv,
+ ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
+ &option_index, &optctx);
if (ret < 0) break;
switch (ret) {
@@ -909,9 +909,10 @@
// only long options
if (long_options[option_index].name == pid_str) {
// ToDo: determine runtime PID_MAX?
- if (!getSizeTArg(optarg, &pid, 1)) {
+ if (!getSizeTArg(optctx.optarg, &pid, 1)) {
logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
- long_options[option_index].name, optarg);
+ long_options[option_index].name,
+ optctx.optarg);
goto exit;
}
break;
@@ -921,9 +922,11 @@
ANDROID_LOG_NONBLOCK;
// ToDo: implement API that supports setting a wrap timeout
size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
- if (optarg && !getSizeTArg(optarg, &dummy, 1)) {
+ if (optctx.optarg &&
+ !getSizeTArg(optctx.optarg, &dummy, 1)) {
logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
- long_options[option_index].name, optarg);
+ long_options[option_index].name,
+ optctx.optarg);
goto exit;
}
if ((dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) &&
@@ -944,7 +947,8 @@
break;
}
if (long_options[option_index].name == id_str) {
- setId = (optarg && optarg[0]) ? optarg : nullptr;
+ setId = (optctx.optarg && optctx.optarg[0]) ? optctx.optarg
+ : nullptr;
}
break;
@@ -972,12 +976,13 @@
mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
// FALLTHRU
case 'T':
- if (strspn(optarg, "0123456789") != strlen(optarg)) {
- char* cp = parseTime(tail_time, optarg);
+ if (strspn(optctx.optarg, "0123456789") !=
+ strlen(optctx.optarg)) {
+ char* cp = parseTime(tail_time, optctx.optarg);
if (!cp) {
logcat_panic(context, HELP_FALSE,
"-%c \"%s\" not in time format\n", ret,
- optarg);
+ optctx.optarg);
goto exit;
}
if (*cp) {
@@ -987,16 +992,16 @@
fprintf(
context->error,
"WARNING: -%c \"%s\"\"%c%s\" time truncated\n",
- ret, optarg, c, cp + 1);
+ ret, optctx.optarg, c, cp + 1);
}
*cp = c;
}
} else {
- if (!getSizeTArg(optarg, &tail_lines, 1)) {
+ if (!getSizeTArg(optctx.optarg, &tail_lines, 1)) {
if (context->error) {
fprintf(context->error,
"WARNING: -%c %s invalid, setting to 1\n",
- ret, optarg);
+ ret, optctx.optarg);
}
tail_lines = 1;
}
@@ -1008,22 +1013,22 @@
break;
case 'e':
- context->regex = new pcrecpp::RE(optarg);
+ context->regex = new pcrecpp::RE(optctx.optarg);
break;
case 'm': {
char* end = nullptr;
- if (!getSizeTArg(optarg, &context->maxCount)) {
+ if (!getSizeTArg(optctx.optarg, &context->maxCount)) {
logcat_panic(context, HELP_FALSE,
"-%c \"%s\" isn't an "
"integer greater than zero\n",
- ret, optarg);
+ ret, optctx.optarg);
goto exit;
}
} break;
case 'g':
- if (!optarg) {
+ if (!optctx.optarg) {
getLogSize = true;
break;
}
@@ -1031,8 +1036,8 @@
case 'G': {
char* cp;
- if (strtoll(optarg, &cp, 0) > 0) {
- setLogSize = strtoll(optarg, &cp, 0);
+ if (strtoll(optctx.optarg, &cp, 0) > 0) {
+ setLogSize = strtoll(optctx.optarg, &cp, 0);
} else {
setLogSize = 0;
}
@@ -1065,42 +1070,42 @@
} break;
case 'p':
- if (!optarg) {
+ if (!optctx.optarg) {
getPruneList = true;
break;
}
// FALLTHRU
case 'P':
- setPruneList = optarg;
+ setPruneList = optctx.optarg;
break;
case 'b': {
- std::unique_ptr<char, void (*)(void*)> buffers(strdup(optarg),
- free);
- optarg = buffers.get();
+ std::unique_ptr<char, void (*)(void*)> buffers(
+ strdup(optctx.optarg), free);
+ char* arg = buffers.get();
unsigned idMask = 0;
char* sv = nullptr; // protect against -ENOMEM above
- while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
- if (!strcmp(optarg, "default")) {
+ while (!!(arg = strtok_r(arg, delimiters, &sv))) {
+ if (!strcmp(arg, "default")) {
idMask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) |
(1 << LOG_ID_CRASH);
- } else if (!strcmp(optarg, "all")) {
+ } else if (!strcmp(arg, "all")) {
allSelected = true;
idMask = (unsigned)-1;
} else {
- log_id_t log_id = android_name_to_log_id(optarg);
+ log_id_t log_id = android_name_to_log_id(arg);
const char* name = android_log_id_to_name(log_id);
- if (!!strcmp(name, optarg)) {
+ if (!!strcmp(name, arg)) {
logcat_panic(context, HELP_TRUE,
- "unknown buffer %s\n", optarg);
+ "unknown buffer %s\n", arg);
goto exit;
}
if (log_id == LOG_ID_SECURITY) allSelected = false;
idMask |= (1 << log_id);
}
- optarg = nullptr;
+ arg = nullptr;
}
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
@@ -1111,7 +1116,7 @@
if (!(idMask & (1 << i))) continue;
bool found = false;
- for (dev = devices; dev; dev = dev->next) {
+ for (dev = context->devices; dev; dev = dev->next) {
if (!strcmp(name, dev->device)) {
found = true;
break;
@@ -1128,7 +1133,7 @@
dev->next = d;
dev = d;
} else {
- devices = dev = d;
+ context->devices = dev = d;
}
context->devCount++;
}
@@ -1140,47 +1145,51 @@
case 'f':
if ((tail_time == log_time::EPOCH) && !tail_lines) {
- tail_time = lastLogTime(optarg);
+ tail_time = lastLogTime(optctx.optarg);
}
// redirect output to a file
- context->outputFileName = optarg;
+ context->outputFileName = optctx.optarg;
break;
case 'r':
- if (!getSizeTArg(optarg, &context->logRotateSizeKBytes, 1)) {
+ if (!getSizeTArg(optctx.optarg, &context->logRotateSizeKBytes,
+ 1)) {
logcat_panic(context, HELP_TRUE,
- "Invalid parameter \"%s\" to -r\n", optarg);
+ "Invalid parameter \"%s\" to -r\n",
+ optctx.optarg);
goto exit;
}
break;
case 'n':
- if (!getSizeTArg(optarg, &context->maxRotatedLogs, 1)) {
+ if (!getSizeTArg(optctx.optarg, &context->maxRotatedLogs, 1)) {
logcat_panic(context, HELP_TRUE,
- "Invalid parameter \"%s\" to -n\n", optarg);
+ "Invalid parameter \"%s\" to -n\n",
+ optctx.optarg);
goto exit;
}
break;
case 'v': {
- if (!strcmp(optarg, "help") || !strcmp(optarg, "--help")) {
+ if (!strcmp(optctx.optarg, "help") ||
+ !strcmp(optctx.optarg, "--help")) {
show_format_help(context);
context->retval = EXIT_SUCCESS;
goto exit;
}
- std::unique_ptr<char, void (*)(void*)> formats(strdup(optarg),
- free);
- optarg = formats.get();
+ std::unique_ptr<char, void (*)(void*)> formats(
+ strdup(optctx.optarg), free);
+ char* arg = formats.get();
unsigned idMask = 0;
char* sv = nullptr; // protect against -ENOMEM above
- while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
- err = setLogFormat(context, optarg);
+ while (!!(arg = strtok_r(arg, delimiters, &sv))) {
+ err = setLogFormat(context, arg);
if (err < 0) {
logcat_panic(context, HELP_FORMAT,
- "Invalid parameter \"%s\" to -v\n", optarg);
+ "Invalid parameter \"%s\" to -v\n", arg);
goto exit;
}
- optarg = nullptr;
+ arg = nullptr;
if (err) hasSetLogFormat = true;
}
} break;
@@ -1249,12 +1258,12 @@
case ':':
logcat_panic(context, HELP_TRUE,
- "Option -%c needs an argument\n", optopt);
+ "Option -%c needs an argument\n", optctx.optopt);
goto exit;
default:
logcat_panic(context, HELP_TRUE, "Unrecognized Option %c\n",
- optopt);
+ optctx.optopt);
goto exit;
}
}
@@ -1277,8 +1286,8 @@
context->printItAnyways = false;
}
- if (!devices) {
- dev = devices = new log_device_t("main", false);
+ if (!context->devices) {
+ dev = context->devices = new log_device_t("main", false);
context->devCount = 1;
if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
dev = dev->next = new log_device_t("system", false);
@@ -1343,7 +1352,7 @@
"Invalid filter expression in logcat args\n");
goto exit;
}
- } else if (argc == optind) {
+ } else if (argc == optctx.optind) {
// Add from environment variable
const char* env_tags_orig = android::getenv(context, "ANDROID_LOG_TAGS");
@@ -1359,7 +1368,7 @@
}
} else {
// Add from commandline
- for (int i = optind ; i < argc ; i++) {
+ for (int i = optctx.optind ; i < argc ; i++) {
// skip stderr redirections of _all_ kinds
if ((argv[i][0] == '2') && (argv[i][1] == '>')) continue;
// skip stdout redirections of _all_ kinds
@@ -1374,7 +1383,7 @@
}
}
- dev = devices;
+ dev = context->devices;
if (tail_time != log_time::EPOCH) {
logger_list = android_logger_list_alloc_time(mode, tail_time, pid);
} else {
@@ -1585,7 +1594,7 @@
}
log_device_t* d;
- for (d = devices; d; d = d->next) {
+ for (d = context->devices; d; d = d->next) {
if (android_name_to_log_id(d->device) == log_msg.id()) break;
}
if (!d) {
@@ -1607,6 +1616,11 @@
}
close:
+ // Short and sweet. Implemented generic version in android_logcat_destroy.
+ while (!!(dev = context->devices)) {
+ context->devices = dev->next;
+ delete dev;
+ }
android_logger_list_free(logger_list);
exit:
@@ -1780,6 +1794,20 @@
android_closeEventTagMap(context->eventTagMap);
+ // generic cleanup of devices list to handle all possible dirty cases
+ log_device_t* dev;
+ while (!!(dev = context->devices)) {
+ struct logger_list* logger_list = dev->logger_list;
+ if (logger_list) {
+ for (log_device_t* d = dev; d; d = d->next) {
+ if (d->logger_list == logger_list) d->logger_list = nullptr;
+ }
+ android_logger_list_free(logger_list);
+ }
+ context->devices = dev->next;
+ delete dev;
+ }
+
int retval = context->retval;
free(context);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index e03731b..0df6de0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -182,7 +182,10 @@
if (!avcr) return DIFFERENT;
lenr -= avcr - msgr;
if (lenl != lenr) return DIFFERENT;
- if (fastcmp<memcmp>(avcl + strlen(avc),
+ // TODO: After b/35468874 is addressed, revisit "lenl > strlen(avc)"
+ // condition, it might become superflous.
+ if (lenl > strlen(avc) &&
+ fastcmp<memcmp>(avcl + strlen(avc),
avcr + strlen(avc),
lenl - strlen(avc))) return DIFFERENT;
return SAME;
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 4081982..bcdecf2 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -13,10 +13,12 @@
liblog.so
libmediandk.so
libm.so
+libnativewindow.so
libOpenMAXAL.so
libOpenSLES.so
libRS.so
libstdc++.so
+libsync.so
libvulkan.so
libwebviewchromium_plat_support.so
libz.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 9f0cde1..f4da09d 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -13,9 +13,11 @@
liblog.so
libmediandk.so
libm.so
+libnativewindow.so
libOpenMAXAL.so
libOpenSLES.so
libRS.so
libstdc++.so
+libsync.so
libvulkan.so
libz.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c6546b9..085ecaf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -290,6 +290,9 @@
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
+ # Now we can start zygote for devices with file based encryption
+ trigger zygote-start
+
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
@@ -299,6 +302,12 @@
trigger early-boot
trigger boot
+on post-fs-data && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+ start netd
+
+on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+ start zygote
+
on post-fs
start logd
# once everything is setup, no need to modify /
@@ -565,7 +574,6 @@
chown system system /sys/class/leds/red/device/grpfreq
chown system system /sys/class/leds/red/device/grppwm
chown system system /sys/class/leds/red/device/blink
- chown system system /sys/class/timed_output/vibrator/enable
chown system system /sys/module/sco/parameters/disable_esco
chown system system /sys/kernel/ipv4/tcp_wmem_min
chown system system /sys/kernel/ipv4/tcp_wmem_def