Merge "liblog: support extended logger_entry headers"
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/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/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index 618a5c5..2c1b255 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -13,6 +13,10 @@
             enabled: true,
         },
     },
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
 
 cc_library {
@@ -52,4 +56,8 @@
         "-Werror",
         "-Wexit-time-destructors",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
index fcd8c83..caea048 100644
--- a/libstats/push_compat/Android.bp
+++ b/libstats/push_compat/Android.bp
@@ -47,6 +47,7 @@
     defaults: ["libstatspush_compat_defaults"],
     export_include_dirs: ["include"],
     static_libs: ["libgtest_prod"],
+    apex_available: ["com.android.resolv"],
 }
 
 cc_test {
diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp
index 9fd9fbc..690dc94 100644
--- a/libstats/socket/Android.bp
+++ b/libstats/socket/Android.bp
@@ -54,6 +54,7 @@
     name: "libstatssocket_headers",
     export_include_dirs: ["include"],
     host_supported: true,
+    apex_available: ["com.android.resolv"],
 }
 
 cc_benchmark {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 7658d5c..19f95d4 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -59,7 +59,7 @@
 
 // Used to turn on crc checks - verify that the content CRC matches the values
 // specified in the local file header and the central directory.
-static const bool kCrcChecksEnabled = false;
+static constexpr bool kCrcChecksEnabled = false;
 
 // The maximum number of bytes to scan backwards for the EOCD start.
 static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
@@ -1314,11 +1314,15 @@
     if (!writer->Append(&buf[0], block_size)) {
       return kIoError;
     }
-    crc = crc32(crc, &buf[0], block_size);
+    if (crc_out) {
+      crc = crc32(crc, &buf[0], block_size);
+    }
     count += block_size;
   }
 
-  *crc_out = crc;
+  if (crc_out) {
+    *crc_out = crc;
+  }
 
   return 0;
 }
@@ -1331,9 +1335,11 @@
   int32_t return_value = -1;
   uint64_t crc = 0;
   if (method == kCompressStored) {
-    return_value = CopyEntryToWriter(handle->mapped_zip, entry, writer, &crc);
+    return_value =
+        CopyEntryToWriter(handle->mapped_zip, entry, writer, kCrcChecksEnabled ? &crc : nullptr);
   } else if (method == kCompressDeflated) {
-    return_value = InflateEntryToWriter(handle->mapped_zip, entry, writer, &crc);
+    return_value =
+        InflateEntryToWriter(handle->mapped_zip, entry, writer, kCrcChecksEnabled ? &crc : nullptr);
   }
 
   if (!return_value && entry->has_data_descriptor) {
diff --git a/libziparchive/zip_archive_benchmark.cpp b/libziparchive/zip_archive_benchmark.cpp
index 09d3b8a..cfa5912 100644
--- a/libziparchive/zip_archive_benchmark.cpp
+++ b/libziparchive/zip_archive_benchmark.cpp
@@ -17,7 +17,6 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <iostream>
 #include <string>
 #include <tuple>
 #include <vector>
@@ -28,17 +27,20 @@
 #include <ziparchive/zip_archive_stream_entry.h>
 #include <ziparchive/zip_writer.h>
 
-static TemporaryFile* CreateZip() {
-  TemporaryFile* result = new TemporaryFile;
+static std::unique_ptr<TemporaryFile> CreateZip(int size = 4, int count = 1000) {
+  auto result = std::make_unique<TemporaryFile>();
   FILE* fp = fdopen(result->fd, "w");
 
   ZipWriter writer(fp);
   std::string lastName = "file";
-  for (size_t i = 0; i < 1000; i++) {
+  for (size_t i = 0; i < count; i++) {
     // Make file names longer and longer.
     lastName = lastName + std::to_string(i);
     writer.StartEntry(lastName.c_str(), ZipWriter::kCompress);
-    writer.WriteBytes("helo", 4);
+    while (size > 0) {
+      writer.WriteBytes("helo", 4);
+      size -= 4;
+    }
     writer.FinishEntry();
   }
   writer.Finish();
@@ -106,5 +108,28 @@
 }
 BENCHMARK(StartAlignedEntry)->Arg(2)->Arg(16)->Arg(1024)->Arg(4096);
 
+static void ExtractEntry(benchmark::State& state) {
+  std::unique_ptr<TemporaryFile> temp_file(CreateZip(1024 * 1024, 1));
+
+  ZipArchiveHandle handle;
+  ZipEntry data;
+  if (OpenArchive(temp_file->path, &handle)) {
+    state.SkipWithError("Failed to open archive");
+  }
+  if (FindEntry(handle, "file0", &data)) {
+    state.SkipWithError("Failed to find archive entry");
+  }
+
+  std::vector<uint8_t> buffer(1024 * 1024);
+  for (auto _ : state) {
+    if (ExtractToMemory(handle, &data, buffer.data(), uint32_t(buffer.size()))) {
+      state.SkipWithError("Failed to extract archive entry");
+      break;
+    }
+  }
+  CloseArchive(handle);
+}
+
+BENCHMARK(ExtractEntry)->Arg(2)->Arg(16)->Arg(1024);
 
 BENCHMARK_MAIN();