Merge "libunwindstack: support for Armv8.3-A Pointer Authentication"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 7933629..1abeb2e 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -28,6 +28,9 @@
       "name": "fs_mgr_vendor_overlay_test"
     },
     {
+      "name": "init_kill_services_test"
+    },
+    {
       "name": "libpackagelistparser_test"
     },
     {
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index d6f536e..ea50f59 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -876,7 +876,7 @@
                     "-S",
                     std::to_string(sb.st_size),
                     session_id_str,
-                    android::base::StringPrintf("%d_%s", i, android::base::Basename(file).c_str()),
+                    android::base::StringPrintf("%d_%s", i, android::base::Basename(split).c_str()),
                     "-",
             };
 
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index b674a81..db4c479 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -400,12 +400,12 @@
     for (const std::string& path : paths) {
         int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
         if (wd < 0) {
-            PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
+            PLOG(ERROR) << "failed to inotify_add_watch on path '" << path << "'";
             continue;
         }
 
         g_monitored_paths[wd] = path;
-        LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
+        LOG(INFO) << "watch descriptor " << wd << " registered for '" << path << "'";
     }
 
     fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
diff --git a/libpixelflinger/include/pixelflinger/format.h b/libpixelflinger/include/pixelflinger/format.h
index 82eeca4..d429477 100644
--- a/libpixelflinger/include/pixelflinger/format.h
+++ b/libpixelflinger/include/pixelflinger/format.h
@@ -82,7 +82,7 @@
     GGL_INDEX_CR      = 2,
 };
 
-typedef struct {
+typedef struct GGLFormat {
 #ifdef __cplusplus
     enum {
         ALPHA   = GGL_INDEX_ALPHA,
diff --git a/libutils/include/utils/BitSet.h b/libutils/include/utils/BitSet.h
index 1df4626..0fb1a6a 100644
--- a/libutils/include/utils/BitSet.h
+++ b/libutils/include/utils/BitSet.h
@@ -21,9 +21,12 @@
 #include <utils/TypeHelpers.h>
 
 /*
- * Contains some bit manipulation helpers.
+ * A class to provide efficient manipulation of bitsets.
  *
- * DO NOT USE: std::bitset<32> or std::bitset<64> preferred
+ * Consider using std::bitset<32> or std::bitset<64> if all you want is a class to do basic bit
+ * manipulation (i.e. AND / OR / XOR / flip / etc). These classes are only needed if you want to
+ * efficiently perform operations like finding the first set bit in a bitset and you want to
+ * avoid using the built-in functions (e.g. __builtin_clz) on std::bitset::to_ulong.
  */
 
 namespace android {
diff --git a/logd/README.property b/logd/README.property
index ab9c4d4..1d7d990 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -52,6 +52,9 @@
 log.tag.<tag>             string persist The <tag> specific logging level.
 persist.log.tag.<tag>      string build  default for log.tag.<tag>
 
+logd.buffer_type           string (empty) Set the log buffer type.  Current choices are 'simple',
+                                          'chatty', or 'serialized'.  Defaults to 'chatty' if empty.
+
 NB:
 - auto - managed by /init
 - bool+ - "true", "false" and comma separated list of "eng" (forced false if
diff --git a/logd/SerializedFlushToState.cpp b/logd/SerializedFlushToState.cpp
index 2633348..b02ccc3 100644
--- a/logd/SerializedFlushToState.cpp
+++ b/logd/SerializedFlushToState.cpp
@@ -31,7 +31,7 @@
 SerializedFlushToState::~SerializedFlushToState() {
     log_id_for_each(i) {
         if (log_positions_[i]) {
-            log_positions_[i]->buffer_it->DecReaderRefCount(true);
+            log_positions_[i]->buffer_it->DecReaderRefCount();
         }
     }
 }
@@ -78,7 +78,7 @@
             logs_needed_from_next_position_[log_id] = true;
         } else {
             // Otherwise, if there is another buffer piece, move to that and do the same check.
-            buffer_it->DecReaderRefCount(true);
+            buffer_it->DecReaderRefCount();
             ++buffer_it;
             buffer_it->IncReaderRefCount();
             log_positions_[log_id]->read_offset = 0;
@@ -134,7 +134,7 @@
     }
 
     // // Decrease the ref count since we're deleting our reference.
-    buffer_it->DecReaderRefCount(false);
+    buffer_it->DecReaderRefCount();
 
     // Delete in the reference.
     log_positions_[log_id].reset();
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index aec24c3..972a3f3 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -32,12 +32,6 @@
     Init();
 }
 
-SerializedLogBuffer::~SerializedLogBuffer() {
-    if (deleter_thread_.joinable()) {
-        deleter_thread_.join();
-    }
-}
-
 void SerializedLogBuffer::Init() {
     log_id_for_each(i) {
         if (SetSize(i, __android_logger_get_buffer_size(i))) {
@@ -121,54 +115,15 @@
     stats_->set_overhead(log_id, after_size);
 }
 
-void SerializedLogBuffer::StartDeleterThread() {
-    if (deleter_thread_running_) {
-        return;
+void SerializedLogBuffer::RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk) {
+    chunk.IncReaderRefCount();
+    int read_offset = 0;
+    while (read_offset < chunk.write_offset()) {
+        auto* entry = chunk.log_entry(read_offset);
+        stats_->Subtract(entry->ToLogStatisticsElement(log_id));
+        read_offset += entry->total_len();
     }
-    if (deleter_thread_.joinable()) {
-        deleter_thread_.join();
-    }
-    auto new_thread = std::thread([this] { DeleterThread(); });
-    deleter_thread_.swap(new_thread);
-    deleter_thread_running_ = true;
-}
-
-// Decompresses the chunks, call LogStatistics::Subtract() on each entry, then delete the chunks and
-// the list.  Note that the SerializedLogChunk objects have been removed from logs_ and their
-// references have been deleted from any SerializedFlushToState objects, so this can be safely done
-// without holding lock_.  It is done in a separate thread to avoid delaying the writer thread.
-void SerializedLogBuffer::DeleterThread() {
-    prctl(PR_SET_NAME, "logd.deleter");
-    while (true) {
-        std::list<SerializedLogChunk> local_chunks_to_delete;
-        log_id_t log_id;
-        {
-            auto lock = std::lock_guard{lock_};
-            log_id_for_each(i) {
-                if (!chunks_to_delete_[i].empty()) {
-                    local_chunks_to_delete = std::move(chunks_to_delete_[i]);
-                    chunks_to_delete_[i].clear();
-                    log_id = i;
-                    break;
-                }
-            }
-            if (local_chunks_to_delete.empty()) {
-                deleter_thread_running_ = false;
-                return;
-            }
-        }
-
-        for (auto& chunk : local_chunks_to_delete) {
-            chunk.IncReaderRefCount();
-            int read_offset = 0;
-            while (read_offset < chunk.write_offset()) {
-                auto* entry = chunk.log_entry(read_offset);
-                stats_->Subtract(entry->ToLogStatisticsElement(log_id));
-                read_offset += entry->total_len();
-            }
-            chunk.DecReaderRefCount(false);
-        }
-    }
+    chunk.DecReaderRefCount();
 }
 
 void SerializedLogBuffer::NotifyReadersOfPrune(
@@ -194,8 +149,6 @@
         }
     }
 
-    StartDeleterThread();
-
     auto& log_buffer = logs_[log_id];
     auto it = log_buffer.begin();
     while (it != log_buffer.end()) {
@@ -203,7 +156,7 @@
             break;
         }
 
-        // Increment ahead of time since we're going to splice this iterator from the list.
+        // Increment ahead of time since we're going to erase this iterator from the list.
         auto it_to_prune = it++;
 
         // The sequence number check ensures that all readers have read all logs in this chunk, but
@@ -219,8 +172,8 @@
             }
         } else {
             size_t buffer_size = it_to_prune->PruneSize();
-            chunks_to_delete_[log_id].splice(chunks_to_delete_[log_id].end(), log_buffer,
-                                             it_to_prune);
+            RemoveChunkFromStats(log_id, *it_to_prune);
+            log_buffer.erase(it_to_prune);
             if (buffer_size >= bytes_to_free) {
                 return true;
             }
diff --git a/logd/SerializedLogBuffer.h b/logd/SerializedLogBuffer.h
index 2b2559f..a03050e 100644
--- a/logd/SerializedLogBuffer.h
+++ b/logd/SerializedLogBuffer.h
@@ -37,7 +37,6 @@
 class SerializedLogBuffer final : public LogBuffer {
   public:
     SerializedLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats);
-    ~SerializedLogBuffer();
     void Init() override;
 
     int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
@@ -61,11 +60,9 @@
             REQUIRES_SHARED(lock_);
     void NotifyReadersOfPrune(log_id_t log_id, const std::list<SerializedLogChunk>::iterator& chunk)
             REQUIRES(reader_list_->reader_threads_lock());
+    void RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk);
     unsigned long GetSizeUsed(log_id_t id) REQUIRES(lock_);
 
-    void StartDeleterThread() REQUIRES(lock_);
-    void DeleterThread();
-
     LogReaderList* reader_list_;
     LogTags* tags_;
     LogStatistics* stats_;
@@ -74,9 +71,5 @@
     std::list<SerializedLogChunk> logs_[LOG_ID_MAX] GUARDED_BY(lock_);
     RwLock lock_;
 
-    std::list<SerializedLogChunk> chunks_to_delete_[LOG_ID_MAX] GUARDED_BY(lock_);
-    std::thread deleter_thread_ GUARDED_BY(lock_);
-    bool deleter_thread_running_ GUARDED_BY(lock_) = false;
-
     std::atomic<uint64_t> sequence_ = 1;
 };
diff --git a/logd/SerializedLogChunk.cpp b/logd/SerializedLogChunk.cpp
index e444856..de641d6 100644
--- a/logd/SerializedLogChunk.cpp
+++ b/logd/SerializedLogChunk.cpp
@@ -31,7 +31,6 @@
                   << " size used: " << write_offset_
                   << " compressed size: " << compressed_log_.size();
     }
-    contents_.Resize(0);
 }
 
 // TODO: Develop a better reference counting strategy to guard against the case where the writer is
@@ -44,13 +43,13 @@
     CompressionEngine::GetInstance().Decompress(compressed_log_, contents_);
 }
 
-void SerializedLogChunk::DecReaderRefCount(bool compress) {
+void SerializedLogChunk::DecReaderRefCount() {
     CHECK_NE(reader_ref_count_, 0U);
     if (--reader_ref_count_ != 0) {
         return;
     }
-    if (compress && !writer_active_) {
-        Compress();
+    if (!writer_active_) {
+        contents_.Resize(0);
     }
 }
 
@@ -83,18 +82,19 @@
     }
 
     if (new_write_offset == 0) {
-        DecReaderRefCount(false);
+        DecReaderRefCount();
         return true;
     }
 
-    // Clear the old compressed logs and set write_offset_ appropriately for DecReaderRefCount()
-    // to compress the new partially cleared log.
+    // Clear the old compressed logs and set write_offset_ appropriately to compress the new
+    // partially cleared log.
     if (new_write_offset != write_offset_) {
         compressed_log_.Resize(0);
         write_offset_ = new_write_offset;
+        Compress();
     }
 
-    DecReaderRefCount(true);
+    DecReaderRefCount();
 
     return false;
 }
diff --git a/logd/SerializedLogChunk.h b/logd/SerializedLogChunk.h
index 50bae63..0991eac 100644
--- a/logd/SerializedLogChunk.h
+++ b/logd/SerializedLogChunk.h
@@ -30,9 +30,7 @@
 
     void Compress();
     void IncReaderRefCount();
-    // Decrease the reader ref count and compress the log if appropriate.  `compress` should only be
-    // set to false in the case that the log buffer will be deleted afterwards.
-    void DecReaderRefCount(bool compress);
+    void DecReaderRefCount();
 
     // Must have no readers referencing this.  Return true if there are no logs left in this chunk.
     bool ClearUidLogs(uid_t uid, log_id_t log_id, LogStatistics* stats);
@@ -50,8 +48,9 @@
 
     void FinishWriting() {
         writer_active_ = false;
+        Compress();
         if (reader_ref_count_ == 0) {
-            Compress();
+            contents_.Resize(0);
         }
     }
 
diff --git a/logd/SerializedLogChunkTest.cpp b/logd/SerializedLogChunkTest.cpp
index 2b478a3..f10b9c6 100644
--- a/logd/SerializedLogChunkTest.cpp
+++ b/logd/SerializedLogChunkTest.cpp
@@ -113,8 +113,7 @@
 TEST(SerializedLogChunk, catch_DecCompressedRef_CHECK) {
     size_t chunk_size = 10 * 4096;
     auto chunk = SerializedLogChunk{chunk_size};
-    EXPECT_DEATH({ chunk.DecReaderRefCount(true); }, "");
-    EXPECT_DEATH({ chunk.DecReaderRefCount(false); }, "");
+    EXPECT_DEATH({ chunk.DecReaderRefCount(); }, "");
 }
 
 // Check that the CHECK() in ClearUidLogs() if the ref count is greater than 0 is caught.
@@ -123,7 +122,7 @@
     auto chunk = SerializedLogChunk{chunk_size};
     chunk.IncReaderRefCount();
     EXPECT_DEATH({ chunk.ClearUidLogs(1000, LOG_ID_MAIN, nullptr); }, "");
-    chunk.DecReaderRefCount(false);
+    chunk.DecReaderRefCount();
 }
 
 class UidClearTest : public testing::TestWithParam<bool> {
@@ -144,7 +143,7 @@
         check(chunk_);
 
         if (finish_writing) {
-            chunk_.DecReaderRefCount(false);
+            chunk_.DecReaderRefCount();
         }
     }
 
diff --git a/logd/main.cpp b/logd/main.cpp
index 350642b..897e11e 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -38,6 +38,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <cutils/android_get_control_file.h>
 #include <cutils/sockets.h>
@@ -61,6 +62,8 @@
 #include "SerializedLogBuffer.h"
 #include "SimpleLogBuffer.h"
 
+using android::base::GetProperty;
+
 #define KMSG_PRIORITY(PRI)                                 \
     '<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
         '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'
@@ -255,28 +258,33 @@
     // Pruning configuration.
     PruneList prune_list;
 
+    std::string buffer_type = GetProperty("logd.buffer_type", "chatty");
+
     // Partial (required for chatty) or full logging statistics.
     bool enable_full_log_statistics = __android_logger_property_get_bool(
             "logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST |
                                        BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
-    LogStatistics log_statistics(enable_full_log_statistics, false);
+    LogStatistics log_statistics(enable_full_log_statistics, buffer_type == "serialized");
 
-    // Serves the purpose of managing the last logs times read on a
-    // socket connection, and as a reader lock on a range of log
-    // entries.
+    // Serves the purpose of managing the last logs times read on a socket connection, and as a
+    // reader lock on a range of log entries.
     LogReaderList reader_list;
 
     // LogBuffer is the object which is responsible for holding all log entries.
-    LogBuffer* logBuf;
-    if (true) {
-        logBuf = new ChattyLogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
+    LogBuffer* log_buffer = nullptr;
+    if (buffer_type == "chatty") {
+        log_buffer = new ChattyLogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
+    } else if (buffer_type == "serialized") {
+        log_buffer = new SerializedLogBuffer(&reader_list, &log_tags, &log_statistics);
+    } else if (buffer_type == "simple") {
+        log_buffer = new SimpleLogBuffer(&reader_list, &log_tags, &log_statistics);
     } else {
-        logBuf = new SimpleLogBuffer(&reader_list, &log_tags, &log_statistics);
+        LOG(FATAL) << "buffer_type must be one of 'chatty', 'serialized', or 'simple'";
     }
 
     // LogReader listens on /dev/socket/logdr. When a client
     // connects, log entries in the LogBuffer are written to the client.
-    LogReader* reader = new LogReader(logBuf, &reader_list);
+    LogReader* reader = new LogReader(log_buffer, &reader_list);
     if (reader->startListener()) {
         return EXIT_FAILURE;
     }
@@ -284,14 +292,14 @@
     // LogListener listens on /dev/socket/logdw for client
     // initiated log messages. New log entries are added to LogBuffer
     // and LogReader is notified to send updates to connected clients.
-    LogListener* swl = new LogListener(logBuf);
+    LogListener* swl = new LogListener(log_buffer);
     if (!swl->StartListener()) {
         return EXIT_FAILURE;
     }
 
     // Command listener listens on /dev/socket/logd for incoming logd
     // administrative commands.
-    CommandListener* cl = new CommandListener(logBuf, &log_tags, &prune_list, &log_statistics);
+    CommandListener* cl = new CommandListener(log_buffer, &log_tags, &prune_list, &log_statistics);
     if (cl->startListener()) {
         return EXIT_FAILURE;
     }
@@ -304,12 +312,12 @@
         int dmesg_fd = __android_logger_property_get_bool("ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE)
                                ? fdDmesg
                                : -1;
-        al = new LogAudit(logBuf, dmesg_fd, &log_statistics);
+        al = new LogAudit(log_buffer, dmesg_fd, &log_statistics);
     }
 
     LogKlog* kl = nullptr;
     if (klogd) {
-        kl = new LogKlog(logBuf, fdDmesg, fdPmesg, al != nullptr, &log_statistics);
+        kl = new LogKlog(log_buffer, fdDmesg, fdPmesg, al != nullptr, &log_statistics);
     }
 
     readDmesg(al, kl);