Merge "crash_reporter: Fix crash_sender"
diff --git a/adb/Android.mk b/adb/Android.mk
index 7789035..b34a49f 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -118,9 +118,7 @@
LOCAL_STATIC_LIBRARIES := libcrypto_static libbase
LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
-ifneq ($(HOST_OS),windows)
- LOCAL_MULTILIB := 64
-endif
+LOCAL_MULTILIB := first
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -134,7 +132,7 @@
LOCAL_SANITIZE := $(adb_target_sanitize)
LOCAL_STATIC_LIBRARIES := libadbd
-LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
+LOCAL_SHARED_LIBRARIES := libbase libcutils
include $(BUILD_NATIVE_TEST)
# adb_test
@@ -149,7 +147,7 @@
LOCAL_SRC_FILES_linux := $(LIBADB_TEST_linux_SRCS)
LOCAL_SRC_FILES_darwin := $(LIBADB_TEST_darwin_SRCS)
LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := liblog libbase
+LOCAL_SHARED_LIBRARIES := libbase
LOCAL_STATIC_LIBRARIES := \
libadb \
libcrypto_static \
@@ -173,7 +171,7 @@
LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
LOCAL_SRC_FILES := test_track_devices.cpp
LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := liblog libbase
+LOCAL_SHARED_LIBRARIES := libbase
LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
LOCAL_LDLIBS += -lrt -ldl -lpthread
include $(BUILD_HOST_EXECUTABLE)
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 4fe0c25..8d50f46 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -931,6 +931,18 @@
return 0;
}
+// Disallow stdin, stdout, and stderr.
+static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
+#ifdef _WIN32
+ const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
+ return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
+ (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
+ (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
+#else
+ return ack_reply_fd > 2;
+#endif
+}
+
int adb_commandline(int argc, const char **argv) {
int no_daemon = 0;
int is_daemon = 0;
@@ -980,14 +992,7 @@
argc--;
argv++;
ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
-#ifdef _WIN32
- const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
- if ((GetStdHandle(STD_INPUT_HANDLE) == ack_reply_handle) ||
- (GetStdHandle(STD_OUTPUT_HANDLE) == ack_reply_handle) ||
- (GetStdHandle(STD_ERROR_HANDLE) == ack_reply_handle)) {
-#else
- if (ack_reply_fd <= 2) { // Disallow stdin, stdout, and stderr.
-#endif
+ if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
return usage();
}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 08d0671..cf2965e 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -3,13 +3,14 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c
+LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c fs_mgr_slotselect.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE:= libfs_mgr
LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static libsquashfs_utils
-LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils
+LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils \
+ bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index d77d41f..4f18339 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -20,8 +20,6 @@
#include <string.h>
#include <sys/mount.h>
-#include <cutils/properties.h>
-
#include "fs_mgr_priv.h"
struct fs_mgr_flag_values {
@@ -310,25 +308,13 @@
fstab->recs[cnt].partnum = flag_vals.partnum;
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
fstab->recs[cnt].zram_size = flag_vals.zram_size;
-
- /* If an A/B partition, modify block device to be the real block device */
- if (fstab->recs[cnt].fs_mgr_flags & MF_SLOTSELECT) {
- char propbuf[PROPERTY_VALUE_MAX];
- char *tmp;
-
- /* use the kernel parameter if set */
- property_get("ro.boot.slot_suffix", propbuf, "");
-
- if (asprintf(&tmp, "%s%s", fstab->recs[cnt].blk_device, propbuf) > 0) {
- free(fstab->recs[cnt].blk_device);
- fstab->recs[cnt].blk_device = tmp;
- } else {
- ERROR("Error updating block device name\n");
- goto err;
- }
- }
cnt++;
}
+ /* If an A/B partition, modify block device to be the real block device */
+ if (fs_mgr_update_for_slotselect(fstab) != 0) {
+ ERROR("Error updating for slotselect\n");
+ goto err;
+ }
fclose(fstab_file);
free(line);
return fstab;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index cc02bac..992b544 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -82,6 +82,7 @@
#define DM_BUF_SIZE 4096
int fs_mgr_set_blk_ro(const char *blockdev);
+int fs_mgr_update_for_slotselect(struct fstab *fstab);
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_slotselect.c b/fs_mgr/fs_mgr_slotselect.c
new file mode 100644
index 0000000..99dcd0e
--- /dev/null
+++ b/fs_mgr/fs_mgr_slotselect.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/properties.h>
+
+#include "fs_mgr.h"
+#include "fs_mgr_priv.h"
+
+#include "bootloader.h"
+
+// Copies slot_suffix from misc into |out_suffix|. Returns 0 on
+// success, -1 on error or if there is no non-empty slot_suffix.
+static int get_active_slot_suffix_from_misc(struct fstab *fstab,
+ char *out_suffix,
+ size_t suffix_len)
+{
+ int n;
+ int misc_fd;
+ ssize_t num_read;
+ struct bootloader_message msg;
+
+ misc_fd = -1;
+ for (n = 0; n < fstab->num_entries; n++) {
+ if (strcmp(fstab->recs[n].mount_point, "/misc") == 0) {
+ misc_fd = open(fstab->recs[n].blk_device, O_RDONLY);
+ if (misc_fd == -1) {
+ ERROR("Error opening misc partition \"%s\" (%s)\n",
+ fstab->recs[n].blk_device,
+ strerror(errno));
+ return -1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (misc_fd == -1) {
+ ERROR("Error finding misc partition\n");
+ return -1;
+ }
+
+ num_read = TEMP_FAILURE_RETRY(read(misc_fd, &msg, sizeof(msg)));
+ // Linux will never return partial reads when reading from block
+ // devices so no need to worry about them.
+ if (num_read != sizeof(msg)) {
+ ERROR("Error reading bootloader_message (%s)\n", strerror(errno));
+ close(misc_fd);
+ return -1;
+ }
+ close(misc_fd);
+ if (msg.slot_suffix[0] == '\0')
+ return -1;
+ strncpy(out_suffix, msg.slot_suffix, suffix_len);
+ return 0;
+}
+
+// Gets slot_suffix from either the kernel cmdline / firmware, the
+// misc partition or built-in fallback.
+static void get_active_slot_suffix(struct fstab *fstab, char *out_suffix,
+ size_t suffix_len)
+{
+ char propbuf[PROPERTY_VALUE_MAX];
+
+ // Get the suffix from the kernel commandline (note that we don't
+ // allow the empty suffix). On bootloaders natively supporting A/B
+ // we'll hit this path every time so don't bother logging it.
+ property_get("ro.boot.slot_suffix", propbuf, "");
+ if (propbuf[0] != '\0') {
+ strncpy(out_suffix, propbuf, suffix_len);
+ return;
+ }
+
+ // If we couldn't get the suffix from the kernel cmdline, try the
+ // the misc partition.
+ if (get_active_slot_suffix_from_misc(fstab, out_suffix, suffix_len) == 0) {
+ INFO("Using slot suffix \"%s\" from misc\n", out_suffix);
+ return;
+ }
+
+ // If that didn't work, fall back to _a. The reasoning here is
+ // that since the fstab has the slotselect option set (otherwise
+ // we wouldn't end up here) we must assume that partitions are
+ // indeed set up for A/B. This corner-case is important because we
+ // may be on this codepath on newly provisioned A/B devices where
+ // misc isn't set up properly (it's just zeroes) and the
+ // bootloader does not (yet) natively support A/B.
+ //
+ // Why '_a'? Because that's what system/extras/boot_control_copy
+ // is using and since the bootloader isn't A/B aware we assume
+ // slots are set up this way.
+ WARNING("Could not determine slot suffix, falling back to \"_a\"\n");
+ strncpy(out_suffix, "_a", suffix_len);
+ return;
+}
+
+// Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error.
+int fs_mgr_update_for_slotselect(struct fstab *fstab)
+{
+ int n;
+ char suffix[PROPERTY_VALUE_MAX];
+ int got_suffix = 0;
+
+ for (n = 0; n < fstab->num_entries; n++) {
+ if (fstab->recs[n].fs_mgr_flags & MF_SLOTSELECT) {
+ char *tmp;
+
+ if (!got_suffix) {
+ memset(suffix, '\0', sizeof(suffix));
+ get_active_slot_suffix(fstab, suffix, sizeof(suffix) - 1);
+ got_suffix = 1;
+ }
+
+ if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device,
+ suffix) > 0) {
+ free(fstab->recs[n].blk_device);
+ fstab->recs[n].blk_device = tmp;
+ } else {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 0582a5f..c2f846e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -242,8 +242,8 @@
LogBufferElementCollection::iterator it, bool engageStats) {
LogBufferElement *e = *it;
log_id_t id = e->getLogId();
- LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
+ LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
if ((f != mLastWorstUid[id].end()) && (it == f->second)) {
mLastWorstUid[id].erase(f);
}
@@ -329,7 +329,51 @@
// prune "pruneRows" of type "id" from the buffer.
//
+// This garbage collection task is used to expire log entries. It is called to
+// remove all logs (clear), all UID logs (unprivileged clear), or every
+// 256 or 10% of the total logs (whichever is less) to prune the logs.
+//
+// First there is a prep phase where we discover the reader region lock that
+// acts as a backstop to any pruning activity to stop there and go no further.
+//
+// There are three major pruning loops that follow. All expire from the oldest
+// entries. Since there are multiple log buffers, the Android logging facility
+// will appear to drop entries 'in the middle' when looking at multiple log
+// sources and buffers. This effect is slightly more prominent when we prune
+// the worst offender by logging source. Thus the logs slowly loose content
+// and value as you move back in time. This is preferred since chatty sources
+// invariably move the logs value down faster as less chatty sources would be
+// expired in the noise.
+//
+// The first loop performs blacklisting and worst offender pruning. Falling
+// through when there are no notable worst offenders and have not hit the
+// region lock preventing further worst offender pruning. This loop also looks
+// after managing the chatty log entries and merging to help provide
+// statistical basis for blame. The chatty entries are not a notification of
+// how much logs you may have, but instead represent how much logs you would
+// have had in a virtual log buffer that is extended to cover all the in-memory
+// logs without loss. They last much longer than the represented pruned logs
+// since they get multiplied by the gains in the non-chatty log sources.
+//
+// The second loop get complicated because an algorithm of watermarks and
+// history is maintained to reduce the order and keep processing time
+// down to a minimum at scale. These algorithms can be costly in the face
+// of larger log buffers, or severly limited processing time granted to a
+// background task at lowest priority.
+//
+// This second loop does straight-up expiration from the end of the logs
+// (again, remember for the specified log buffer id) but does some whitelist
+// preservation. Thus whitelist is a Hail Mary low priority, blacklists and
+// spam filtration all take priority. This second loop also checks if a region
+// lock is causing us to buffer too much in the logs to help the reader(s),
+// and will tell the slowest reader thread to skip log entries, and if
+// persistent and hits a further threshold, kill the reader thread.
+//
+// The third thread is optional, and only gets hit if there was a whitelist
+// and more needs to be pruned against the backstop of the region lock.
+//
// mLogElementsLock must be held when this function is called.
+//
void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
LogTimeEntry *oldest = NULL;
@@ -410,7 +454,12 @@
bool kick = false;
bool leading = true;
it = mLogElements.begin();
- if (worst != (uid_t) -1) {
+ // Perform at least one mandatory garbage collection cycle in following
+ // - clear leading chatty tags
+ // - merge chatty tags
+ // - check age-out of preserved logs
+ bool gc = pruneRows <= 1;
+ if (!gc && (worst != (uid_t) -1)) {
LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(worst);
if ((f != mLastWorstUid[id].end())
&& (f->second != mLogElements.end())) {
@@ -481,7 +530,7 @@
// unmerged drop message
if (dropped) {
last.add(e);
- if ((e->getUid() == worst)
+ if ((!gc && (e->getUid() == worst))
|| (mLastWorstUid[id].find(e->getUid())
== mLastWorstUid[id].end())) {
mLastWorstUid[id][e->getUid()] = it;
@@ -516,7 +565,10 @@
it = erase(it, false);
} else {
last.add(e);
- mLastWorstUid[id][e->getUid()] = it;
+ if (!gc || (mLastWorstUid[id].find(worst)
+ == mLastWorstUid[id].end())) {
+ mLastWorstUid[id][worst] = it;
+ }
++it;
}
}