Merge changes I8fd2a3c9,Id08058f3

* changes:
  Set apex_available property
  Set apex_available property
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 8b67e22..599f500 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -258,7 +258,7 @@
     props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
 
     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
-        props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
+        props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath);
 
     if (!mHealthdConfig->batteryFullChargePath.isEmpty())
         props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index bd71cb5..ef8ffbe 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -234,7 +234,16 @@
         old_root_dir.reset();
     }
 
-    Modprobe m({"/lib/modules"});
+    std::string module_load_file = "modules.load";
+    if (IsRecoveryMode() && !ForceNormalBoot(cmdline)) {
+        struct stat fileStat;
+        std::string recovery_load_path = "/lib/modules/modules.load.recovery";
+        if (!stat(recovery_load_path.c_str(), &fileStat)) {
+            module_load_file = "modules.load.recovery";
+        }
+    }
+
+    Modprobe m({"/lib/modules"}, module_load_file);
     auto want_console = ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline);
     if (!m.LoadListedModules(!want_console)) {
         if (want_console) {
diff --git a/init/service.cpp b/init/service.cpp
index b12d11a..20400a0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -90,7 +90,9 @@
                        << "\") has incorrect label or no domain transition from " << mycon.get()
                        << " to another SELinux domain defined. Have you configured your "
                           "service correctly? https://source.android.com/security/selinux/"
-                          "device-policy#label_new_services_and_address_denials";
+                          "device-policy#label_new_services_and_address_denials. Note: this "
+                          "error shows up even in permissive mode in order to make auditing "
+                          "denials possible.";
     }
     if (rc < 0) {
         return Error() << "Could not get process context";
diff --git a/init/test_kill_services/Android.bp b/init/test_kill_services/Android.bp
index f6e85e2..d59e548 100644
--- a/init/test_kill_services/Android.bp
+++ b/init/test_kill_services/Android.bp
@@ -3,5 +3,9 @@
     srcs: ["init_kill_services_test.cpp"],
     shared_libs: ["libbase"],
     test_suites: ["general-tests"],
-    require_root: true,
+
+    // TODO(b/153565474): switch back to auto-generation
+    // and add back:
+    //     require_root: true,
+    auto_gen_config: false,
 }
diff --git a/init/test_kill_services/AndroidTest.xml b/init/test_kill_services/AndroidTest.xml
new file mode 100644
index 0000000..c1dcd59
--- /dev/null
+++ b/init/test_kill_services/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Runs init_kill_services_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <!-- cannot be autogenerated: b/153565474 -->
+    <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="init_kill_services_test->/data/local/tmp/init_kill_services_test" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="init_kill_services_test" />
+    </test>
+</configuration>
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index ee6ae7a..297036e 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -24,7 +24,7 @@
 
 class Modprobe {
   public:
-    Modprobe(const std::vector<std::string>&);
+    Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load");
 
     bool LoadListedModules(bool strict = true);
     bool LoadWithAliases(const std::string& module_name, bool strict,
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index f22bbf1..d193796 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -312,7 +312,7 @@
     }
 }
 
-Modprobe::Modprobe(const std::vector<std::string>& base_paths) {
+Modprobe::Modprobe(const std::vector<std::string>& base_paths, const std::string load_file) {
     using namespace std::placeholders;
 
     for (const auto& base_path : base_paths) {
@@ -326,7 +326,7 @@
         ParseCfg(base_path + "/modules.softdep", softdep_callback);
 
         auto load_callback = std::bind(&Modprobe::ParseLoadCallback, this, _1);
-        ParseCfg(base_path + "/modules.load", load_callback);
+        ParseCfg(base_path + "/" + load_file, load_callback);
 
         auto options_callback = std::bind(&Modprobe::ParseOptionsCallback, this, _1);
         ParseCfg(base_path + "/modules.options", options_callback);
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index bf63abf..8fc3d23 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -50,6 +50,22 @@
 
 std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
                                          MapInfo* info) {
+  if (UNLIKELY(!HasDexSupport())) {
+    return nullptr;
+  }
+
+  size_t max_size = info->end - dex_file_offset_in_memory;
+  if (memory->IsLocal()) {
+    size_t size = max_size;
+
+    std::string err_msg;
+    std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory(
+        reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg);
+    if (art_dex_file != nullptr && size <= max_size) {
+      return std::unique_ptr<DexFile>(new DexFile(art_dex_file));
+    }
+  }
+
   if (!info->name.empty()) {
     std::unique_ptr<DexFile> dex_file =
         DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
@@ -57,7 +73,7 @@
       return dex_file;
     }
   }
-  return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
+  return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size);
 }
 
 bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
@@ -94,7 +110,8 @@
 
 std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
                                                              Memory* memory,
-                                                             const std::string& name) {
+                                                             const std::string& name,
+                                                             size_t max_size) {
   if (UNLIKELY(!HasDexSupport())) {
     return nullptr;
   }
@@ -105,6 +122,9 @@
     std::string error_msg;
     std::unique_ptr<art_api::dex::DexFile> art_dex_file =
         OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
+    if (size > max_size) {
+      return nullptr;
+    }
 
     if (art_dex_file != nullptr) {
       return std::unique_ptr<DexFileFromMemory>(
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index 4e8369f..fe185da 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -55,7 +55,8 @@
 class DexFileFromMemory : public DexFile {
  public:
   static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
-                                                   Memory* memory, const std::string& name);
+                                                   Memory* memory, const std::string& name,
+                                                   size_t max_size);
 
  private:
   DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file,
diff --git a/libunwindstack/MemoryLocal.h b/libunwindstack/MemoryLocal.h
index 29aaf12..7e027cf 100644
--- a/libunwindstack/MemoryLocal.h
+++ b/libunwindstack/MemoryLocal.h
@@ -28,6 +28,8 @@
   MemoryLocal() = default;
   virtual ~MemoryLocal() = default;
 
+  bool IsLocal() const override { return true; }
+
   size_t Read(uint64_t addr, void* dst, size_t size) override;
 };
 
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index 3106564..ecd908a 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -41,6 +41,8 @@
 
   virtual void Clear() {}
 
+  virtual bool IsLocal() const { return false; }
+
   virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
 
   bool ReadFully(uint64_t addr, void* dst, size_t size);
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index dc935a3..1deba01 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -21,6 +21,7 @@
 
 #include <unordered_map>
 
+#include <MemoryLocal.h>
 #include <android-base/file.h>
 #include <gtest/gtest.h>
 #include <unwindstack/MapInfo.h>
@@ -109,7 +110,7 @@
 
   memory.SetMemory(0x1000, kDexData, 10);
 
-  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
+  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
 }
 
 TEST(DexFileTest, from_memory_fail_too_small_for_data) {
@@ -117,7 +118,7 @@
 
   memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
 
-  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
+  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
 }
 
 TEST(DexFileTest, from_memory_open) {
@@ -125,7 +126,7 @@
 
   memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
 
-  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
+  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
 }
 
 TEST(DexFileTest, from_memory_no_leak) {
@@ -136,7 +137,7 @@
   size_t first_allocated_bytes = 0;
   size_t last_allocated_bytes = 0;
   for (size_t i = 0; i < kNumLeakLoops; i++) {
-    EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
+    EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
     ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
   }
 }
@@ -213,6 +214,43 @@
   EXPECT_TRUE(dex_file == nullptr);
 }
 
+TEST(DexFileTest, create_using_memory_size_too_small) {
+  MemoryFake memory;
+  memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
+  MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist");
+  EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
+}
+
+class MemoryLocalFake : public MemoryLocal {
+ public:
+  MemoryLocalFake(size_t memory_size) : backing_(memory_size) {}
+  virtual ~MemoryLocalFake() = default;
+
+  void* Data() { return backing_.data(); }
+
+ private:
+  std::vector<void*> backing_;
+};
+
+TEST(DexFileTest, create_using_local_memory) {
+  MemoryLocalFake memory(sizeof(kDexData));
+
+  memcpy(memory.Data(), kDexData, sizeof(kDexData));
+  uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
+  MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist");
+  EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr);
+}
+
+TEST(DexFileTest, create_using_local_memory_size_too_small) {
+  MemoryLocalFake memory(sizeof(kDexData));
+
+  memcpy(memory.Data(), kDexData, sizeof(kDexData));
+  uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
+  MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5,
+               "/does/not/exist");
+  EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr);
+}
+
 TEST(DexFileTest, get_method) {
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 8f9774f..7658d5c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -1009,19 +1009,17 @@
 // the data appended to it.
 class MemoryWriter : public zip_archive::Writer {
  public:
-  static MemoryWriter Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
+  static std::unique_ptr<MemoryWriter> Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
     const uint64_t declared_length = entry->uncompressed_length;
     if (declared_length > size) {
       ALOGW("Zip: file size %" PRIu64 " is larger than the buffer size %zu.", declared_length,
             size);
-      return MemoryWriter{nullptr, 0};
+      return nullptr;
     }
 
-    return MemoryWriter(buf, size);
+    return std::unique_ptr<MemoryWriter>(new MemoryWriter(buf, size));
   }
 
-  bool IsValid() const { return buf_ != nullptr; }
-
   virtual bool Append(uint8_t* buf, size_t buf_size) override {
     if (size_ < buf_size || bytes_written_ > size_ - buf_size) {
       ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
@@ -1053,17 +1051,17 @@
   // block device).
   //
   // Returns a valid FileWriter on success, |nullptr| if an error occurred.
-  static FileWriter Create(int fd, const ZipEntry64* entry) {
+  static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry64* entry) {
     const uint64_t declared_length = entry->uncompressed_length;
     const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
     if (current_offset == -1) {
       ALOGW("Zip: unable to seek to current location on fd %d: %s", fd, strerror(errno));
-      return FileWriter{};
+      return nullptr;
     }
 
     if (declared_length > SIZE_MAX || declared_length > INT64_MAX) {
       ALOGW("Zip: file size %" PRIu64 " is too large to extract.", declared_length);
-      return FileWriter{};
+      return nullptr;
     }
 
 #if defined(__linux__)
@@ -1081,7 +1079,7 @@
       if (result == -1 && errno == ENOSPC) {
         ALOGW("Zip: unable to allocate %" PRIu64 " bytes at offset %" PRId64 ": %s",
               declared_length, static_cast<int64_t>(current_offset), strerror(errno));
-        return FileWriter{};
+        return nullptr;
       }
     }
 #endif  // __linux__
@@ -1089,7 +1087,7 @@
     struct stat sb;
     if (fstat(fd, &sb) == -1) {
       ALOGW("Zip: unable to fstat file: %s", strerror(errno));
-      return FileWriter{};
+      return nullptr;
     }
 
     // Block device doesn't support ftruncate(2).
@@ -1098,11 +1096,11 @@
       if (result == -1) {
         ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
-        return FileWriter{};
+        return nullptr;
       }
     }
 
-    return FileWriter(fd, declared_length);
+    return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
   }
 
   FileWriter(FileWriter&& other) noexcept
@@ -1112,8 +1110,6 @@
     other.fd_ = -1;
   }
 
-  bool IsValid() const { return fd_ != -1; }
-
   virtual bool Append(uint8_t* buf, size_t buf_size) override {
     if (declared_length_ < buf_size || total_bytes_written_ > declared_length_ - buf_size) {
       ALOGW("Zip: Unexpected size %zu  (declared) vs %zu (actual)", declared_length_,
@@ -1365,11 +1361,11 @@
 int32_t ExtractToMemory(ZipArchiveHandle archive, const ZipEntry64* entry, uint8_t* begin,
                         size_t size) {
   auto writer = MemoryWriter::Create(begin, size, entry);
-  if (!writer.IsValid()) {
+  if (!writer) {
     return kIoError;
   }
 
-  return ExtractToWriter(archive, entry, &writer);
+  return ExtractToWriter(archive, entry, writer.get());
 }
 
 int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry* entry, int fd) {
@@ -1379,11 +1375,11 @@
 
 int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry64* entry, int fd) {
   auto writer = FileWriter::Create(fd, entry);
-  if (!writer.IsValid()) {
+  if (!writer) {
     return kIoError;
   }
 
-  return ExtractToWriter(archive, entry, &writer);
+  return ExtractToWriter(archive, entry, writer.get());
 }
 
 int GetFileDescriptor(const ZipArchiveHandle archive) {
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 3d4e580..f5429be 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -344,8 +344,8 @@
   // Known facts about a.txt, from zipinfo -v.
   ASSERT_EQ(63, data.offset);
   ASSERT_EQ(kCompressDeflated, data.method);
-  ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
-  ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
+  ASSERT_EQ(17u, data.uncompressed_length);
+  ASSERT_EQ(13u, data.compressed_length);
   ASSERT_EQ(0x950821c5, data.crc32);
   ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
 
@@ -505,9 +505,12 @@
 
   ZipEntry64 entry;
   ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
-  ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
+  ASSERT_EQ(0u, entry.uncompressed_length);
+  // Extraction to a 1 byte buffer should succeed.
   uint8_t buffer[1];
   ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
+  // Extraction to an empty buffer should succeed.
+  ASSERT_EQ(0, ExtractToMemory(handle, &entry, nullptr, 0));
 
   TemporaryFile tmp_output_file;
   ASSERT_NE(-1, tmp_output_file.fd);
@@ -782,7 +785,7 @@
   // "abdcdefghijk").
   ZipEntry64 entry;
   ASSERT_EQ(0, FindEntry(handle, "name", &entry));
-  ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
+  ASSERT_EQ(12u, entry.uncompressed_length);
 
   entry_out->resize(12);
   (*error_code_out) = ExtractToMemory(handle, &entry, &((*entry_out)[0]), 12);
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index bd17555..0845504 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -49,18 +49,8 @@
                 return;
             }
             if (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec) {
-                if (mReader.logbuf().isMonotonic()) {
-                    LogTimeEntry::unlock();
-                    return;
-                }
-                // If the user changes the time in a gross manner that
-                // invalidates the timeout, fall through and trigger.
-                log_time now(CLOCK_REALTIME);
-                if (((entry->mEnd + entry->mTimeout) > now) &&
-                    (now > entry->mEnd)) {
-                    LogTimeEntry::unlock();
-                    return;
-                }
+                LogTimeEntry::unlock();
+                return;
             }
             entry->triggerReader_Locked();
             LogTimeEntry::unlock();
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index ceaf393..a69d439 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -16,7 +16,7 @@
 #ifndef _FLUSH_COMMAND_H
 #define _FLUSH_COMMAND_H
 
-#include <private/android_logger.h>
+#include <android/log.h>
 #include <sysutils/SocketClientCommand.h>
 
 class LogBufferElement;
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1cf2061..5bec076 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -27,6 +27,7 @@
 #include <unistd.h>
 
 #include <unordered_map>
+#include <utility>
 
 #include <cutils/properties.h>
 #include <private/android_logger.h>
@@ -43,8 +44,6 @@
 // Default
 #define log_buffer_size(id) mMaxSize[id]
 
-const log_time LogBuffer::pruneMargin(3, 0);
-
 void LogBuffer::init() {
     log_id_for_each(i) {
         mLastSet[i] = false;
@@ -390,59 +389,7 @@
 
 // assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
 void LogBuffer::log(LogBufferElement* elem) {
-    // cap on how far back we will sort in-place, otherwise append
-    static uint32_t too_far_back = 5;  // five seconds
-    // Insert elements in time sorted order if possible
-    //  NB: if end is region locked, place element at end of list
-    LogBufferElementCollection::iterator it = mLogElements.end();
-    LogBufferElementCollection::iterator last = it;
-    if (__predict_true(it != mLogElements.begin())) --it;
-    if (__predict_false(it == mLogElements.begin()) ||
-        __predict_true((*it)->getRealTime() <= elem->getRealTime()) ||
-        __predict_false((((*it)->getRealTime().tv_sec - too_far_back) >
-                         elem->getRealTime().tv_sec) &&
-                        (elem->getLogId() != LOG_ID_KERNEL) &&
-                        ((*it)->getLogId() != LOG_ID_KERNEL))) {
-        mLogElements.push_back(elem);
-    } else {
-        log_time end(log_time::EPOCH);
-        bool end_set = false;
-        bool end_always = false;
-
-        LogTimeEntry::rdlock();
-
-        LastLogTimes::iterator times = mTimes.begin();
-        while (times != mTimes.end()) {
-            LogTimeEntry* entry = times->get();
-            if (!entry->mNonBlock) {
-                end_always = true;
-                break;
-            }
-            // it passing mEnd is blocked by the following checks.
-            if (!end_set || (end <= entry->mEnd)) {
-                end = entry->mEnd;
-                end_set = true;
-            }
-            times++;
-        }
-
-        if (end_always || (end_set && (end > (*it)->getRealTime()))) {
-            mLogElements.push_back(elem);
-        } else {
-            // should be short as timestamps are localized near end()
-            do {
-                last = it;
-                if (__predict_false(it == mLogElements.begin())) {
-                    break;
-                }
-                --it;
-            } while (((*it)->getRealTime() > elem->getRealTime()) &&
-                     (!end_set || (end <= (*it)->getRealTime())));
-            mLogElements.insert(last, elem);
-        }
-        LogTimeEntry::unlock();
-    }
-
+    mLogElements.push_back(elem);
     stats.add(elem);
     maybePrune(elem->getLogId());
 }
@@ -614,12 +561,11 @@
     }
 
     void clear(LogBufferElement* element) {
-        log_time current =
-            element->getRealTime() - log_time(EXPIRE_RATELIMIT, 0);
+        uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
         for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
             LogBufferElement* mapElement = it->second;
-            if ((mapElement->getDropped() >= EXPIRE_THRESHOLD) &&
-                (current > mapElement->getRealTime())) {
+            if (mapElement->getDropped() >= EXPIRE_THRESHOLD &&
+                current > mapElement->getRealTime().nsec()) {
                 it = map.erase(it);
             } else {
                 ++it;
@@ -628,16 +574,6 @@
     }
 };
 
-// Determine if watermark is within pruneMargin + 1s from the end of the list,
-// the caller will use this result to set an internal busy flag indicating
-// the prune operation could not be completed because a reader is blocking
-// the request.
-bool LogBuffer::isBusy(log_time watermark) {
-    LogBufferElementCollection::iterator ei = mLogElements.end();
-    --ei;
-    return watermark < ((*ei)->getRealTime() - pruneMargin - log_time(1, 0));
-}
-
 // If the selected reader is blocking our pruning progress, decide on
 // what kind of mitigation is necessary to unblock the situation.
 void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
@@ -726,8 +662,6 @@
         }
         times++;
     }
-    log_time watermark(log_time::tv_sec_max, log_time::tv_nsec_max);
-    if (oldest) watermark = oldest->mStart - pruneMargin;
 
     LogBufferElementCollection::iterator it;
 
@@ -749,9 +683,9 @@
                 mLastSet[id] = true;
             }
 
-            if (oldest && (watermark <= element->getRealTime())) {
-                busy = isBusy(watermark);
-                if (busy) kickMe(oldest, id, pruneRows);
+            if (oldest && oldest->mStart <= element->getSequence()) {
+                busy = true;
+                kickMe(oldest, id, pruneRows);
                 break;
             }
 
@@ -837,8 +771,8 @@
         while (it != mLogElements.end()) {
             LogBufferElement* element = *it;
 
-            if (oldest && (watermark <= element->getRealTime())) {
-                busy = isBusy(watermark);
+            if (oldest && oldest->mStart <= element->getSequence()) {
+                busy = true;
                 // Do not let chatty eliding trigger any reader mitigation
                 break;
             }
@@ -989,9 +923,9 @@
             mLastSet[id] = true;
         }
 
-        if (oldest && (watermark <= element->getRealTime())) {
-            busy = isBusy(watermark);
-            if (!whitelist && busy) kickMe(oldest, id, pruneRows);
+        if (oldest && oldest->mStart <= element->getSequence()) {
+            busy = true;
+            if (!whitelist) kickMe(oldest, id, pruneRows);
             break;
         }
 
@@ -1022,9 +956,9 @@
                 mLastSet[id] = true;
             }
 
-            if (oldest && (watermark <= element->getRealTime())) {
-                busy = isBusy(watermark);
-                if (busy) kickMe(oldest, id, pruneRows);
+            if (oldest && oldest->mStart <= element->getSequence()) {
+                busy = true;
+                kickMe(oldest, id, pruneRows);
                 break;
             }
 
@@ -1111,43 +1045,32 @@
     return retval;
 }
 
-log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
-                            pid_t* lastTid, bool privileged, bool security,
-                            int (*filter)(const LogBufferElement* element,
-                                          void* arg),
-                            void* arg) {
+uint64_t LogBuffer::flushTo(SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged,
+                            bool security,
+                            int (*filter)(const LogBufferElement* element, void* arg), void* arg) {
     LogBufferElementCollection::iterator it;
     uid_t uid = reader->getUid();
 
     rdlock();
 
-    if (start == log_time::EPOCH) {
+    if (start <= 1) {
         // client wants to start from the beginning
         it = mLogElements.begin();
     } else {
-        // Cap to 300 iterations we look back for out-of-order entries.
-        size_t count = 300;
-
         // Client wants to start from some specified time. Chances are
         // we are better off starting from the end of the time sorted list.
-        LogBufferElementCollection::iterator last;
-        for (last = it = mLogElements.end(); it != mLogElements.begin();
+        for (it = mLogElements.end(); it != mLogElements.begin();
              /* do nothing */) {
             --it;
             LogBufferElement* element = *it;
-            if (element->getRealTime() > start) {
-                last = it;
-            } else if (element->getRealTime() == start) {
-                last = ++it;
-                break;
-            } else if (!--count) {
+            if (element->getSequence() <= start) {
+                it++;
                 break;
             }
         }
-        it = last;
     }
 
-    log_time curr = start;
+    uint64_t curr = start;
 
     LogBufferElement* lastElement = nullptr;  // iterator corruption paranoia
     static const size_t maxSkip = 4194304;    // maximum entries to skip
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index c2d5b97..16225a5 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -118,11 +118,10 @@
     // lastTid is an optional context to help detect if the last previous
     // valid message was from the same source so we can differentiate chatty
     // filter types (identical or expired)
-    log_time flushTo(SocketClient* writer, const log_time& start,
+    uint64_t flushTo(SocketClient* writer, uint64_t start,
                      pid_t* lastTid,  // &lastTid[LOG_ID_MAX] or nullptr
                      bool privileged, bool security,
-                     int (*filter)(const LogBufferElement* element,
-                                   void* arg) = nullptr,
+                     int (*filter)(const LogBufferElement* element, void* arg) = nullptr,
                      void* arg = nullptr);
 
     bool clear(log_id_t id, uid_t uid = AID_ROOT);
@@ -175,10 +174,8 @@
    private:
     static constexpr size_t minPrune = 4;
     static constexpr size_t maxPrune = 256;
-    static const log_time pruneMargin;
 
     void maybePrune(log_id_t id);
-    bool isBusy(log_time watermark);
     void kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows);
 
     bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index ec81933..3714800 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -30,15 +30,15 @@
 #include "LogReader.h"
 #include "LogUtils.h"
 
-const log_time LogBufferElement::FLUSH_ERROR((uint32_t)-1, (uint32_t)-1);
+const uint64_t LogBufferElement::FLUSH_ERROR(0);
 atomic_int_fast64_t LogBufferElement::sequence(1);
 
-LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
-                                   uid_t uid, pid_t pid, pid_t tid,
-                                   const char* msg, uint16_t len)
+LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
+                                   pid_t tid, const char* msg, uint16_t len)
     : mUid(uid),
       mPid(pid),
       mTid(tid),
+      mSequence(sequence.fetch_add(1, memory_order_relaxed)),
       mRealTime(realtime),
       mMsgLen(len),
       mLogId(log_id),
@@ -51,6 +51,7 @@
     : mUid(elem.mUid),
       mPid(elem.mPid),
       mTid(elem.mTid),
+      mSequence(elem.mSequence),
       mRealTime(elem.mRealTime),
       mMsgLen(elem.mMsgLen),
       mLogId(elem.mLogId),
@@ -244,7 +245,7 @@
     return retval;
 }
 
-log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent, bool lastSame) {
+uint64_t LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent, bool lastSame) {
     struct logger_entry entry = {};
 
     entry.hdr_size = sizeof(struct logger_entry);
@@ -263,7 +264,7 @@
 
     if (mDropped) {
         entry.len = populateDroppedMessage(buffer, parent, lastSame);
-        if (!entry.len) return mRealTime;
+        if (!entry.len) return mSequence;
         iovec[1].iov_base = buffer;
     } else {
         entry.len = mMsgLen;
@@ -271,9 +272,7 @@
     }
     iovec[1].iov_len = entry.len;
 
-    log_time retval = reader->sendDatav(iovec, 1 + (entry.len != 0))
-                          ? FLUSH_ERROR
-                          : mRealTime;
+    uint64_t retval = reader->sendDatav(iovec, 1 + (entry.len != 0)) ? FLUSH_ERROR : mSequence;
 
     if (buffer) free(buffer);
 
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index fd790e4..434b7db 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -39,6 +39,7 @@
     const uint32_t mUid;
     const uint32_t mPid;
     const uint32_t mTid;
+    uint64_t mSequence;
     log_time mRealTime;
     union {
         char* mMsg;    // mDropped == false
@@ -90,10 +91,12 @@
     const char* getMsg() const {
         return mDropped ? nullptr : mMsg;
     }
+    uint64_t getSequence() const { return mSequence; }
+    static uint64_t getCurrentSequence() { return sequence.load(memory_order_relaxed); }
     log_time getRealTime(void) const {
         return mRealTime;
     }
 
-    static const log_time FLUSH_ERROR;
-    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool lastSame);
+    static const uint64_t FLUSH_ERROR;
+    uint64_t flushTo(SocketClient* writer, LogBuffer* parent, bool lastSame);
 };
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 9db8c00..f79d39c 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -89,8 +89,7 @@
     static const char _timeout[] = " timeout=";
     cp = strstr(buffer, _timeout);
     if (cp) {
-        timeout = atol(cp + sizeof(_timeout) - 1) * NS_PER_SEC +
-                  log_time(CLOCK_REALTIME).nsec();
+        timeout = atol(cp + sizeof(_timeout) - 1) * NS_PER_SEC + log_time(CLOCK_MONOTONIC).nsec();
     }
 
     unsigned int logMask = -1;
@@ -130,70 +129,53 @@
         nonBlock = true;
     }
 
-    log_time sequence = start;
-    //
-    // This somewhat expensive data validation operation is required
-    // for non-blocking, with timeout.  The incoming timestamp must be
-    // in range of the list, if not, return immediately.  This is
-    // used to prevent us from from getting stuck in timeout processing
-    // with an invalid time.
-    //
-    // Find if time is really present in the logs, monotonic or real, implicit
-    // conversion from monotonic or real as necessary to perform the check.
-    // Exit in the check loop ASAP as you find a transition from older to
-    // newer, but use the last entry found to ensure overlap.
-    //
-    if (nonBlock && (sequence != log_time::EPOCH) && timeout) {
-        class LogFindStart {  // A lambda by another name
-           private:
+    uint64_t sequence = 1;
+    // Convert realtime to sequence number
+    if (start != log_time::EPOCH) {
+        class LogFindStart {
             const pid_t mPid;
             const unsigned mLogMask;
-            bool mStartTimeSet;
-            log_time mStart;
-            log_time& mSequence;
-            log_time mLast;
-            bool mIsMonotonic;
+            bool startTimeSet;
+            const log_time start;
+            uint64_t& sequence;
+            uint64_t last;
+            bool isMonotonic;
 
-           public:
-            LogFindStart(pid_t pid, unsigned logMask, log_time& sequence,
+          public:
+            LogFindStart(unsigned logMask, pid_t pid, log_time start, uint64_t& sequence,
                          bool isMonotonic)
                 : mPid(pid),
                   mLogMask(logMask),
-                  mStartTimeSet(false),
-                  mStart(sequence),
-                  mSequence(sequence),
-                  mLast(sequence),
-                  mIsMonotonic(isMonotonic) {
-            }
+                  startTimeSet(false),
+                  start(start),
+                  sequence(sequence),
+                  last(sequence),
+                  isMonotonic(isMonotonic) {}
 
             static int callback(const LogBufferElement* element, void* obj) {
                 LogFindStart* me = reinterpret_cast<LogFindStart*>(obj);
                 if ((!me->mPid || (me->mPid == element->getPid())) &&
                     (me->mLogMask & (1 << element->getLogId()))) {
-                    log_time real = element->getRealTime();
-                    if (me->mStart == real) {
-                        me->mSequence = real;
-                        me->mStartTimeSet = true;
+                    if (me->start == element->getRealTime()) {
+                        me->sequence = element->getSequence();
+                        me->startTimeSet = true;
                         return -1;
-                    } else if (!me->mIsMonotonic || android::isMonotonic(real)) {
-                        if (me->mStart < real) {
-                            me->mSequence = me->mLast;
-                            me->mStartTimeSet = true;
+                    } else if (!me->isMonotonic || android::isMonotonic(element->getRealTime())) {
+                        if (me->start < element->getRealTime()) {
+                            me->sequence = me->last;
+                            me->startTimeSet = true;
                             return -1;
                         }
-                        me->mLast = real;
+                        me->last = element->getSequence();
                     } else {
-                        me->mLast = real;
+                        me->last = element->getSequence();
                     }
                 }
                 return false;
             }
 
-            bool found() {
-                return mStartTimeSet;
-            }
-
-        } logFindStart(pid, logMask, sequence,
+            bool found() { return startTimeSet; }
+        } logFindStart(logMask, pid, start, sequence,
                        logbuf().isMonotonic() && android::isMonotonic(start));
 
         logbuf().flushTo(cli, sequence, nullptr, FlushCommand::hasReadLogs(cli),
@@ -201,24 +183,27 @@
                          logFindStart.callback, &logFindStart);
 
         if (!logFindStart.found()) {
-            doSocketDelete(cli);
-            return false;
+            if (nonBlock) {
+                doSocketDelete(cli);
+                return false;
+            }
+            sequence = LogBufferElement::getCurrentSequence();
         }
     }
 
     android::prdebug(
-        "logdr: UID=%d GID=%d PID=%d %c tail=%lu logMask=%x pid=%d "
-        "start=%" PRIu64 "ns timeout=%" PRIu64 "ns\n",
-        cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail,
-        logMask, (int)pid, sequence.nsec(), timeout);
+            "logdr: UID=%d GID=%d PID=%d %c tail=%lu logMask=%x pid=%d "
+            "start=%" PRIu64 "ns timeout=%" PRIu64 "ns\n",
+            cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail, logMask,
+            (int)pid, start.nsec(), timeout);
 
-    if (sequence == log_time::EPOCH) {
+    if (start == log_time::EPOCH) {
         timeout = 0;
     }
 
     LogTimeEntry::wrlock();
-    auto entry = std::make_unique<LogTimeEntry>(
-        *this, cli, nonBlock, tail, logMask, pid, sequence, timeout);
+    auto entry = std::make_unique<LogTimeEntry>(*this, cli, nonBlock, tail, logMask, pid, start,
+                                                sequence, timeout);
     if (!entry->startReader_Locked()) {
         LogTimeEntry::unlock();
         return false;
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 208d67f..ed8d2f5 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -18,8 +18,6 @@
 #include <string.h>
 #include <sys/prctl.h>
 
-#include <private/android_logger.h>
-
 #include "FlushCommand.h"
 #include "LogBuffer.h"
 #include "LogReader.h"
@@ -27,9 +25,9 @@
 
 pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
 
-LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client,
-                           bool nonBlock, unsigned long tail, log_mask_t logMask,
-                           pid_t pid, log_time start, uint64_t timeout)
+LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
+                           unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time,
+                           uint64_t start, uint64_t timeout)
     : leadingDropped(false),
       mReader(reader),
       mLogMask(logMask),
@@ -38,9 +36,9 @@
       mTail(tail),
       mIndex(0),
       mClient(client),
+      mStartTime(start_time),
       mStart(start),
-      mNonBlock(nonBlock),
-      mEnd(log_time(android_log_clockid())) {
+      mNonBlock(nonBlock) {
     mTimeout.tv_sec = timeout / NS_PER_SEC;
     mTimeout.tv_nsec = timeout % NS_PER_SEC;
     memset(mLastTid, 0, sizeof(mLastTid));
@@ -81,12 +79,12 @@
 
     wrlock();
 
-    log_time start = me->mStart;
+    uint64_t start = me->mStart;
 
     while (!me->mRelease) {
         if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
-            if (pthread_cond_timedwait(&me->threadTriggeredCondition,
-                                       &timesLock, &me->mTimeout) == ETIMEDOUT) {
+            if (pthread_cond_clockwait(&me->threadTriggeredCondition, &timesLock, CLOCK_MONOTONIC,
+                                       &me->mTimeout) == ETIMEDOUT) {
                 me->mTimeout.tv_sec = 0;
                 me->mTimeout.tv_nsec = 0;
             }
@@ -105,13 +103,22 @@
         start = logbuf.flushTo(client, start, me->mLastTid, privileged,
                                security, FilterSecondPass, me);
 
+        // We only ignore entries before the original start time for the first flushTo(), if we
+        // get entries after this first flush before the original start time, then the client
+        // wouldn't have seen them.
+        // Note: this is still racy and may skip out of order events that came in since the last
+        // time the client disconnected and then reconnected with the new start time.  The long term
+        // solution here is that clients must request events since a specific sequence number.
+        me->mStartTime.tv_sec = 0;
+        me->mStartTime.tv_nsec = 0;
+
         wrlock();
 
         if (start == LogBufferElement::FLUSH_ERROR) {
             break;
         }
 
-        me->mStart = start + log_time(0, 1);
+        me->mStart = start + 1;
 
         if (me->mNonBlock || me->mRelease) {
             break;
@@ -158,11 +165,11 @@
     }
 
     if (me->mCount == 0) {
-        me->mStart = element->getRealTime();
+        me->mStart = element->getSequence();
     }
 
-    if ((!me->mPid || (me->mPid == element->getPid())) &&
-        (me->isWatching(element->getLogId()))) {
+    if ((!me->mPid || me->mPid == element->getPid()) && me->isWatching(element->getLogId()) &&
+        (me->mStartTime == log_time::EPOCH || me->mStartTime <= element->getRealTime())) {
         ++me->mCount;
     }
 
@@ -177,7 +184,7 @@
 
     LogTimeEntry::wrlock();
 
-    me->mStart = element->getRealTime();
+    me->mStart = element->getSequence();
 
     if (me->skipAhead[element->getLogId()]) {
         me->skipAhead[element->getLogId()]--;
@@ -204,6 +211,10 @@
         goto skip;
     }
 
+    if (me->mStartTime != log_time::EPOCH && element->getRealTime() <= me->mStartTime) {
+        goto skip;
+    }
+
     if (me->mRelease) {
         goto stop;
     }
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 9f6f203..a99c73b 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -49,16 +49,16 @@
     unsigned long mTail;
     unsigned long mIndex;
 
-   public:
-    LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
-                 unsigned long tail, log_mask_t logMask, pid_t pid,
-                 log_time start, uint64_t timeout);
+  public:
+    LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock, unsigned long tail,
+                 log_mask_t logMask, pid_t pid, log_time start_time, uint64_t sequence,
+                 uint64_t timeout);
 
     SocketClient* mClient;
-    log_time mStart;
-    struct timespec mTimeout;
+    log_time mStartTime;
+    uint64_t mStart;
+    struct timespec mTimeout;  // CLOCK_MONOTONIC based timeout used for log wrapping.
     const bool mNonBlock;
-    const log_time mEnd;  // only relevant if mNonBlock
 
     // Protect List manipulations
     static void wrlock(void) {