Merge "Allow parsing zip entries larger than 4GiB"
diff --git a/adb/Android.bp b/adb/Android.bp
index a557090..12d9a14 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -317,8 +317,8 @@
     static_libs: [
         "libadb_crypto",
         "libadb_host",
-	"libadb_pairing_auth",
-	"libadb_pairing_connection",
+        "libadb_pairing_auth",
+        "libadb_pairing_connection",
         "libadb_protos",
         "libadb_tls_connection",
         "libandroidfw",
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 0844428..2ed58b2 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -42,7 +42,7 @@
 #include "adb_client.h"
 #include "adb_io.h"
 #include "adb_utils.h"
-#include "brotli_utils.h"
+#include "compression_utils.h"
 #include "file_sync_protocol.h"
 #include "line_printer.h"
 #include "sysdeps/errno.h"
@@ -580,8 +580,8 @@
 
             while (true) {
                 Block output;
-                BrotliEncodeResult result = encoder.Encode(&output);
-                if (result == BrotliEncodeResult::Error) {
+                EncodeResult result = encoder.Encode(&output);
+                if (result == EncodeResult::Error) {
                     Error("compressing '%s' locally failed", lpath.c_str());
                     return false;
                 }
@@ -592,12 +592,12 @@
                     WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + output.size());
                 }
 
-                if (result == BrotliEncodeResult::Done) {
+                if (result == EncodeResult::Done) {
                     sending = false;
                     break;
-                } else if (result == BrotliEncodeResult::NeedInput) {
+                } else if (result == EncodeResult::NeedInput) {
                     break;
-                } else if (result == BrotliEncodeResult::MoreOutput) {
+                } else if (result == EncodeResult::MoreOutput) {
                     continue;
                 }
             }
@@ -1076,9 +1076,9 @@
 
         while (true) {
             std::span<char> output;
-            BrotliDecodeResult result = decoder.Decode(&output);
+            DecodeResult result = decoder.Decode(&output);
 
-            if (result == BrotliDecodeResult::Error) {
+            if (result == DecodeResult::Error) {
                 sc.Error("decompress failed");
                 adb_unlink(lpath);
                 return false;
@@ -1097,15 +1097,15 @@
             sc.RecordBytesTransferred(msg.data.size);
             sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, expected_size);
 
-            if (result == BrotliDecodeResult::NeedInput) {
+            if (result == DecodeResult::NeedInput) {
                 break;
-            } else if (result == BrotliDecodeResult::MoreOutput) {
+            } else if (result == DecodeResult::MoreOutput) {
                 continue;
-            } else if (result == BrotliDecodeResult::Done) {
+            } else if (result == DecodeResult::Done) {
                 reading = false;
                 break;
             } else {
-                LOG(FATAL) << "invalid BrotliDecodeResult: " << static_cast<int>(result);
+                LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result);
             }
         }
     }
diff --git a/adb/brotli_utils.h b/adb/compression_utils.h
similarity index 88%
rename from adb/brotli_utils.h
rename to adb/compression_utils.h
index c5be73d..c445095 100644
--- a/adb/brotli_utils.h
+++ b/adb/compression_utils.h
@@ -23,7 +23,14 @@
 
 #include "types.h"
 
-enum class BrotliDecodeResult {
+enum class DecodeResult {
+    Error,
+    Done,
+    NeedInput,
+    MoreOutput,
+};
+
+enum class EncodeResult {
     Error,
     Done,
     NeedInput,
@@ -38,7 +45,7 @@
 
     void Append(Block&& block) { input_buffer_.append(std::move(block)); }
 
-    BrotliDecodeResult Decode(std::span<char>* output) {
+    DecodeResult Decode(std::span<char>* output) {
         size_t available_in = input_buffer_.front_size();
         const uint8_t* next_in = reinterpret_cast<const uint8_t*>(input_buffer_.front_data());
 
@@ -56,16 +63,16 @@
 
         switch (r) {
             case BROTLI_DECODER_RESULT_SUCCESS:
-                return BrotliDecodeResult::Done;
+                return DecodeResult::Done;
             case BROTLI_DECODER_RESULT_ERROR:
-                return BrotliDecodeResult::Error;
+                return DecodeResult::Error;
             case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
                 // Brotli guarantees as one of its invariants that if it returns NEEDS_MORE_INPUT,
                 // it will consume the entire input buffer passed in, so we don't have to worry
                 // about bytes left over in the front block with more input remaining.
-                return BrotliDecodeResult::NeedInput;
+                return DecodeResult::NeedInput;
             case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
-                return BrotliDecodeResult::MoreOutput;
+                return DecodeResult::MoreOutput;
         }
     }
 
@@ -75,13 +82,6 @@
     std::unique_ptr<BrotliDecoderState, void (*)(BrotliDecoderState*)> decoder_;
 };
 
-enum class BrotliEncodeResult {
-    Error,
-    Done,
-    NeedInput,
-    MoreOutput,
-};
-
 template <size_t OutputBlockSize>
 struct BrotliEncoder {
     explicit BrotliEncoder()
@@ -95,7 +95,7 @@
     void Append(Block input) { input_buffer_.append(std::move(input)); }
     void Finish() { finished_ = true; }
 
-    BrotliEncodeResult Encode(Block* output) {
+    EncodeResult Encode(Block* output) {
         output->clear();
         while (true) {
             size_t available_in = input_buffer_.front_size();
@@ -112,7 +112,7 @@
 
             if (!BrotliEncoderCompressStream(encoder_.get(), op, &available_in, &next_in,
                                              &available_out, &next_out, nullptr)) {
-                return BrotliEncodeResult::Error;
+                return EncodeResult::Error;
             }
 
             size_t bytes_consumed = input_buffer_.front_size() - available_in;
@@ -123,14 +123,14 @@
             if (BrotliEncoderIsFinished(encoder_.get())) {
                 output_block_.resize(OutputBlockSize - output_bytes_left_);
                 *output = std::move(output_block_);
-                return BrotliEncodeResult::Done;
+                return EncodeResult::Done;
             } else if (output_bytes_left_ == 0) {
                 *output = std::move(output_block_);
                 output_block_.resize(OutputBlockSize);
                 output_bytes_left_ = OutputBlockSize;
-                return BrotliEncodeResult::MoreOutput;
+                return EncodeResult::MoreOutput;
             } else if (input_buffer_.empty()) {
-                return BrotliEncodeResult::NeedInput;
+                return EncodeResult::NeedInput;
             }
         }
     }
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 07f6e65..5ccddea 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -57,7 +57,7 @@
 #include "adb_io.h"
 #include "adb_trace.h"
 #include "adb_utils.h"
-#include "brotli_utils.h"
+#include "compression_utils.h"
 #include "file_sync_protocol.h"
 #include "security_log_tags.h"
 #include "sysdeps/errno.h"
@@ -288,8 +288,8 @@
 
         while (true) {
             std::span<char> output;
-            BrotliDecodeResult result = decoder.Decode(&output);
-            if (result == BrotliDecodeResult::Error) {
+            DecodeResult result = decoder.Decode(&output);
+            if (result == DecodeResult::Error) {
                 SendSyncFailErrno(s, "decompress failed");
                 return false;
             }
@@ -299,14 +299,14 @@
                 return false;
             }
 
-            if (result == BrotliDecodeResult::NeedInput) {
+            if (result == DecodeResult::NeedInput) {
                 break;
-            } else if (result == BrotliDecodeResult::MoreOutput) {
+            } else if (result == DecodeResult::MoreOutput) {
                 continue;
-            } else if (result == BrotliDecodeResult::Done) {
+            } else if (result == DecodeResult::Done) {
                 break;
             } else {
-                LOG(FATAL) << "invalid BrotliDecodeResult: " << static_cast<int>(result);
+                LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result);
             }
         }
     }
@@ -591,7 +591,6 @@
 static bool recv_uncompressed(borrowed_fd s, unique_fd fd, std::vector<char>& buffer) {
     syncmsg msg;
     msg.data.id = ID_DATA;
-    std::optional<BrotliEncoder<SYNC_DATA_MAX>> encoder;
     while (true) {
         int r = adb_read(fd.get(), &buffer[0], buffer.size() - sizeof(msg.data));
         if (r <= 0) {
@@ -633,8 +632,8 @@
 
         while (true) {
             Block output;
-            BrotliEncodeResult result = encoder.Encode(&output);
-            if (result == BrotliEncodeResult::Error) {
+            EncodeResult result = encoder.Encode(&output);
+            if (result == EncodeResult::Error) {
                 SendSyncFailErrno(s, "compress failed");
                 return false;
             }
@@ -647,12 +646,12 @@
                 }
             }
 
-            if (result == BrotliEncodeResult::Done) {
+            if (result == EncodeResult::Done) {
                 sending = false;
                 break;
-            } else if (result == BrotliEncodeResult::NeedInput) {
+            } else if (result == EncodeResult::NeedInput) {
                 break;
-            } else if (result == BrotliEncodeResult::MoreOutput) {
+            } else if (result == EncodeResult::MoreOutput) {
                 continue;
             }
         }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 9a879b5..7ea30d1 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -42,6 +42,12 @@
 #include "sysdeps/network.h"
 #include "sysdeps/stat.h"
 
+#if defined(__APPLE__)
+static void* mempcpy(void* dst, const void* src, size_t n) {
+    return static_cast<char*>(memcpy(dst, src, n)) + n;
+}
+#endif
+
 #ifdef _WIN32
 
 // Clang-only nullability specifiers
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index a9c1676..5d6cee4 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -1238,16 +1238,26 @@
   // Shift last_reboot_reason_property to last_last_reboot_reason_property
   std::string last_boot_reason;
   if (!android::base::ReadFileToString(last_reboot_reason_file, &last_boot_reason)) {
+    PLOG(ERROR) << "Failed to read " << last_reboot_reason_file;
     last_boot_reason = android::base::GetProperty(last_reboot_reason_property, "");
+    LOG(INFO) << "Value of " << last_reboot_reason_property << " : " << last_boot_reason;
+  } else {
+    LOG(INFO) << "Last reboot reason read from " << last_reboot_reason_file << " : "
+              << last_boot_reason << ". Last reboot reason read from "
+              << last_reboot_reason_property << " : "
+              << android::base::GetProperty(last_reboot_reason_property, "");
   }
   if (last_boot_reason.empty() || isKernelRebootReason(system_boot_reason)) {
     last_boot_reason = system_boot_reason;
   } else {
     transformReason(last_boot_reason);
   }
+  LOG(INFO) << "Normalized last reboot reason : " << last_boot_reason;
   android::base::SetProperty(last_last_reboot_reason_property, last_boot_reason);
   android::base::SetProperty(last_reboot_reason_property, "");
-  unlink(last_reboot_reason_file);
+  if (unlink(last_reboot_reason_file) != 0) {
+    PLOG(ERROR) << "Failed to unlink " << last_reboot_reason_file;
+  }
 }
 
 // Gets the boot time offset. This is useful when Android is running in a
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
index e52762e..58153f3 100644
--- a/cpio/mkbootfs.c
+++ b/cpio/mkbootfs.c
@@ -13,6 +13,7 @@
 #include <fcntl.h>
 
 #include <private/android_filesystem_config.h>
+#include <private/fs_config.h>
 
 /* NOTES
 **
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index a836d3b..b218f21 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -829,6 +829,20 @@
         return std::set<std::string>(boot_devices.begin(), boot_devices.end());
     }
 
+    std::string cmdline;
+    if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
+        std::set<std::string> boot_devices;
+        const std::string cmdline_key = "androidboot.boot_device";
+        for (const auto& [key, value] : fs_mgr_parse_boot_config(cmdline)) {
+            if (key == cmdline_key) {
+                boot_devices.emplace(value);
+            }
+        }
+        if (!boot_devices.empty()) {
+            return boot_devices;
+        }
+    }
+
     // Fallback to extract boot devices from fstab.
     Fstab fstab;
     if (!ReadDefaultFstab(&fstab)) {
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index d670ca0..996fbca 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -195,6 +195,12 @@
     defaults: ["libsnapshot_test_defaults"],
 }
 
+// For VTS 10
+vts_config {
+    name: "VtsLibsnapshotTest",
+    test_config: "VtsLibsnapshotTest.xml"
+}
+
 cc_binary {
     name: "snapshotctl",
     srcs: [
diff --git a/fs_mgr/libsnapshot/VtsLibsnapshotTest.xml b/fs_mgr/libsnapshot/VtsLibsnapshotTest.xml
new file mode 100644
index 0000000..b53b51e
--- /dev/null
+++ b/fs_mgr/libsnapshot/VtsLibsnapshotTest.xml
@@ -0,0 +1,29 @@
+<?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="Config for VTS VtsLibsnapshotTest">
+    <option name="config-descriptor:metadata" key="plan" value="vts-kernel"/>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsLibsnapshotTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_libsnapshot_test/vts_libsnapshot_test"/>
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_libsnapshot_test/vts_libsnapshot_test"/>
+        <option name="binary-test-type" value="gtest"/>
+        <option name="test-timeout" value="5m"/>
+    </test>
+</configuration>
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index cf324fe..82c4262 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -732,6 +732,7 @@
   grep -v \
     -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\|bpf\) " \
     -e "^\(binfmt_misc\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \
+    -e " functionfs " \
     -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \
     -e "^rootfs / rootfs rw," \
     -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index 0bd4df4..ef9a451 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -32,6 +32,7 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
+#include <generated_android_ids.h>
 #include <hidl/metadata.h>
 #include <property_info_serializer/property_info_serializer.h>
 
@@ -48,9 +49,6 @@
 #include "service_list.h"
 #include "service_parser.h"
 
-#define EXCLUDE_FS_CONFIG_STRUCTURES
-#include "generated_android_ids.h"
-
 using namespace std::literals;
 
 using android::base::ParseInt;
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 1e4e127..842b2e5 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -47,6 +47,7 @@
 #include <thread>
 #include <vector>
 
+#include <InitProperties.sysprop.h>
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -85,6 +86,7 @@
 using android::properties::ParsePropertyInfoFile;
 using android::properties::PropertyInfoAreaFile;
 using android::properties::PropertyInfoEntry;
+using android::sysprop::InitProperties::is_userspace_reboot_supported;
 
 namespace android {
 namespace init {
@@ -489,7 +491,13 @@
         }
         LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
                   << process_log_string;
-        DebugRebootLogging();
+        if (!value.empty()) {
+            DebugRebootLogging();
+        }
+        if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
+            *error = "Userspace reboot is not supported by this device";
+            return PROP_ERROR_INVALID_VALUE;
+        }
     }
 
     // If a process other than init is writing a non-empty value, it means that process is
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 0f4cd0d..c6dcfa2 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -22,8 +22,10 @@
 #include <sys/_system_properties.h>
 
 #include <android-base/properties.h>
+#include <android-base/scopeguard.h>
 #include <gtest/gtest.h>
 
+using android::base::GetProperty;
 using android::base::SetProperty;
 
 namespace android {
@@ -74,5 +76,19 @@
     EXPECT_TRUE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\x80"));
 }
 
+TEST(property_service, userspace_reboot_not_supported) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Skipping test, must be run as root.";
+        return;
+    }
+    const std::string original_value = GetProperty("init.userspace_reboot.is_supported", "");
+    auto guard = android::base::make_scope_guard([&original_value]() {
+        SetProperty("init.userspace_reboot.is_supported", original_value);
+    });
+
+    ASSERT_TRUE(SetProperty("init.userspace_reboot.is_supported", "false"));
+    EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace"));
+}
+
 }  // namespace init
 }  // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 081f695..d2dc6d3 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -102,7 +102,15 @@
     if (write_to_property) {
         SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
     }
-    WriteStringToFile(reason, LAST_REBOOT_REASON_FILE);
+    auto fd = unique_fd(TEMP_FAILURE_RETRY(open(
+            LAST_REBOOT_REASON_FILE, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, 0666)));
+    if (!fd.ok()) {
+        PLOG(ERROR) << "Could not open '" << LAST_REBOOT_REASON_FILE
+                    << "' to persist reboot reason";
+        return;
+    }
+    WriteStringToFd(reason, fd);
+    fsync(fd.get());
 }
 
 // represents umount status during reboot / shutdown.
@@ -317,9 +325,9 @@
                          bool* reboot_monitor_run) {
     unsigned int remaining_shutdown_time = 0;
 
-    // 30 seconds more than the timeout passed to the thread as there is a final Umount pass
+    // 300 seconds more than the timeout passed to the thread as there is a final Umount pass
     // after the timeout is reached.
-    constexpr unsigned int shutdown_watchdog_timeout_default = 30;
+    constexpr unsigned int shutdown_watchdog_timeout_default = 300;
     auto shutdown_watchdog_timeout = android::base::GetUintProperty(
             "ro.build.shutdown.watchdog.timeout", shutdown_watchdog_timeout_default);
     remaining_shutdown_time = shutdown_watchdog_timeout + shutdown_timeout.count() / 1000;
@@ -539,26 +547,6 @@
     Timer t;
     LOG(INFO) << "Reboot start, reason: " << reason << ", reboot_target: " << reboot_target;
 
-    // Ensure last reboot reason is reduced to canonical
-    // alias reported in bootloader or system boot reason.
-    size_t skip = 0;
-    std::vector<std::string> reasons = Split(reason, ",");
-    if (reasons.size() >= 2 && reasons[0] == "reboot" &&
-        (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
-         reasons[1] == "hard" || reasons[1] == "warm")) {
-        skip = strlen("reboot,");
-    }
-    PersistRebootReason(reason.c_str() + skip, true);
-    sync();
-
-    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
-    // worry about unmounting it.
-    if (!IsDataMounted()) {
-        sync();
-        RebootSystem(cmd, reboot_target);
-        abort();
-    }
-
     bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
 
     auto shutdown_timeout = 0ms;
@@ -591,6 +579,25 @@
     // Start reboot monitor thread
     sem_post(&reboot_semaphore);
 
+    // Ensure last reboot reason is reduced to canonical
+    // alias reported in bootloader or system boot reason.
+    size_t skip = 0;
+    std::vector<std::string> reasons = Split(reason, ",");
+    if (reasons.size() >= 2 && reasons[0] == "reboot" &&
+        (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
+         reasons[1] == "hard" || reasons[1] == "warm")) {
+        skip = strlen("reboot,");
+    }
+    PersistRebootReason(reason.c_str() + skip, true);
+
+    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
+    // worry about unmounting it.
+    if (!IsDataMounted()) {
+        sync();
+        RebootSystem(cmd, reboot_target);
+        abort();
+    }
+
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
     const std::set<std::string> to_starts{"watchdogd"};
     std::vector<Service*> stop_first;
diff --git a/init/sysprop/InitProperties.sysprop b/init/sysprop/InitProperties.sysprop
index b876dc0..24c2434 100644
--- a/init/sysprop/InitProperties.sysprop
+++ b/init/sysprop/InitProperties.sysprop
@@ -31,6 +31,6 @@
     type: Boolean
     scope: Public
     access: Readonly
-    prop_name: "ro.init.userspace_reboot.is_supported"
+    prop_name: "init.userspace_reboot.is_supported"
     integer_as_bool: true
 }
diff --git a/init/sysprop/api/com.android.sysprop.init-current.txt b/init/sysprop/api/com.android.sysprop.init-current.txt
index b8bcef9..01f4e9a 100644
--- a/init/sysprop/api/com.android.sysprop.init-current.txt
+++ b/init/sysprop/api/com.android.sysprop.init-current.txt
@@ -2,7 +2,7 @@
   module: "android.sysprop.InitProperties"
   prop {
     api_name: "is_userspace_reboot_supported"
-    prop_name: "ro.init.userspace_reboot.is_supported"
+    prop_name: "init.userspace_reboot.is_supported"
     integer_as_bool: true
   }
   prop {
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index b73a29b..e4f45a8 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -34,14 +34,7 @@
  * partition, from which the system reads passwd and group files.
  */
 
-#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
-#define _ANDROID_FILESYSTEM_CONFIG_H_
-
-#include <sys/types.h>
-
-#if !defined(__ANDROID_VNDK__) && !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
-#include <private/fs_config.h>
-#endif
+#pragma once
 
 /* This is the master Users and Groups config for the platform.
  * DO NOT EVER RENUMBER
@@ -224,5 +217,3 @@
  * documented at the top of this header file.
  * Also see build/tools/fs_config for more details.
  */
-
-#endif
diff --git a/libcutils/include/private/canned_fs_config.h b/libcutils/include/private/canned_fs_config.h
index 135b91c..ad4de4c 100644
--- a/libcutils/include/private/canned_fs_config.h
+++ b/libcutils/include/private/canned_fs_config.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef _CANNED_FS_CONFIG_H
-#define _CANNED_FS_CONFIG_H
+#pragma once
 
 #include <inttypes.h>
+#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
@@ -26,5 +26,3 @@
                       unsigned* gid, unsigned* mode, uint64_t* capabilities);
 
 __END_DECLS
-
-#endif
diff --git a/liblog/README.protocol.md b/liblog/README.protocol.md
index fef29c9..f247b28 100644
--- a/liblog/README.protocol.md
+++ b/liblog/README.protocol.md
@@ -17,6 +17,49 @@
         };
     };
 
+where the embedded structs are defined as:
+
+    struct android_log_header_t {
+        uint8_t id;
+        uint16_t tid;
+        log_time realtime;
+    };
+
+    struct log_time {
+        uint32_t tv_sec = 0;
+        uint32_t tv_nsec = 0;
+    }
+
+    struct android_event_header_t {
+        int32_t tag;
+    };
+
+    struct android_event_list_t {
+        int8_t type;  // EVENT_TYPE_LIST
+        int8_t element_count;
+    };
+
+    struct android_event_float_t {
+        int8_t type;  // EVENT_TYPE_FLOAT
+        float data;
+    };
+
+    struct android_event_int_t {
+        int8_t type;   // EVENT_TYPE_INT
+        int32_t data;
+    } android_event_int_t;
+
+    struct android_event_long_t {
+        int8_t type;   // EVENT_TYPE_LONG
+        int64_t data;
+    };
+
+    struct android_event_string_t {
+        int8_t type;     // EVENT_TYPE_STRING;
+        int32_t length;
+        char data[];
+    };
+
 The payload, excluding the header, has a max size of LOGGER_ENTRY_MAX_PAYLOAD.
 
 ## header
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 2351afa..5efe03f 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -529,6 +529,10 @@
         free(buf);
     } else if (opthdr->nd_opt_type == ND_OPT_DNSSL) {
         // TODO: support DNSSL.
+    } else if (opthdr->nd_opt_type == ND_OPT_CAPTIVE_PORTAL) {
+        // TODO: support CAPTIVE PORTAL.
+    } else if (opthdr->nd_opt_type == ND_OPT_PREF64) {
+        // TODO: support PREF64.
     } else {
         SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type);
         return false;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 341275d..821e042 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -662,7 +662,7 @@
         if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) {
           return "";
         }
-        std::string build_id(hdr.n_descsz - 1, '\0');
+        std::string build_id(hdr.n_descsz, '\0');
         if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) {
           return build_id;
         }
diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
index 6953e26..70e136b 100644
--- a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
+++ b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
@@ -142,15 +142,14 @@
 
   char note_section[128];
   Elf32_Nhdr note_header = {};
-  note_header.n_namesz = 4;   // "GNU"
-  note_header.n_descsz = 12;  // "ELF_BUILDID"
+  note_header.n_namesz = sizeof("GNU");
+  note_header.n_descsz = sizeof("ELF_BUILDID") - 1;
   note_header.n_type = NT_GNU_BUILD_ID;
   memcpy(&note_section, &note_header, sizeof(note_header));
   size_t note_offset = sizeof(note_header);
-  memcpy(&note_section[note_offset], "GNU", sizeof("GNU"));
-  note_offset += sizeof("GNU");
-  memcpy(&note_section[note_offset], "ELF_BUILDID", sizeof("ELF_BUILDID"));
-  note_offset += sizeof("ELF_BUILDID");
+  memcpy(&note_section[note_offset], "GNU", note_header.n_namesz);
+  note_offset += note_header.n_namesz;
+  memcpy(&note_section[note_offset], "ELF_BUILDID", note_header.n_descsz);
 
   Elf32_Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -195,4 +194,10 @@
   MultipleThreadTest("ELF_BUILDID");
 }
 
+TEST_F(MapInfoGetBuildIDTest, real_elf) {
+  MapInfo map_info(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE,
+                   TestGetFileDirectory() + "offline/empty_arm64/libc.so");
+  EXPECT_EQ("6df0590c4920f4c7b9f34fe833f37d54", map_info.GetPrintableBuildID());
+}
+
 }  // namespace unwindstack