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;
                 }
             }