Merge "Remove String16::makeLower()."
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 796a39a..ad48dd1 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -17,6 +17,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -680,7 +681,7 @@
     }
 }
 
-bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab_out) {
     auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
     if (!fstab_file) {
         PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
@@ -689,31 +690,43 @@
 
     bool is_proc_mounts = path == "/proc/mounts";
 
-    if (!ReadFstabFile(fstab_file.get(), is_proc_mounts, fstab)) {
+    Fstab fstab;
+    if (!ReadFstabFile(fstab_file.get(), is_proc_mounts, &fstab)) {
         LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
         return false;
     }
-    if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
-        // This is expected to fail if host is android Q, since Q doesn't
-        // support DSU slotting. The DSU "active" indicator file would be
-        // non-existent or empty if DSU is enabled within the guest system.
-        // In that case, just use the default slot name "dsu".
-        std::string dsu_slot;
-        if (!android::gsi::GetActiveDsu(&dsu_slot)) {
-            PWARNING << __FUNCTION__ << "(): failed to get active dsu slot";
+    if (!is_proc_mounts) {
+        if (!access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
+            // This is expected to fail if host is android Q, since Q doesn't
+            // support DSU slotting. The DSU "active" indicator file would be
+            // non-existent or empty if DSU is enabled within the guest system.
+            // In that case, just use the default slot name "dsu".
+            std::string dsu_slot;
+            if (!android::gsi::GetActiveDsu(&dsu_slot) && errno != ENOENT) {
+                PERROR << __FUNCTION__ << "(): failed to get active DSU slot";
+                return false;
+            }
+            if (dsu_slot.empty()) {
+                dsu_slot = "dsu";
+                LWARNING << __FUNCTION__ << "(): assuming default DSU slot: " << dsu_slot;
+            }
+            // This file is non-existent on Q vendor.
+            std::string lp_names;
+            if (!ReadFileToString(gsi::kGsiLpNamesFile, &lp_names) && errno != ENOENT) {
+                PERROR << __FUNCTION__ << "(): failed to read DSU LP names";
+                return false;
+            }
+            TransformFstabForDsu(&fstab, dsu_slot, Split(lp_names, ","));
+        } else if (errno != ENOENT) {
+            PERROR << __FUNCTION__ << "(): failed to access() DSU booted indicator";
+            return false;
         }
-        if (dsu_slot.empty()) {
-            dsu_slot = "dsu";
-        }
-
-        std::string lp_names;
-        ReadFileToString(gsi::kGsiLpNamesFile, &lp_names);
-        TransformFstabForDsu(fstab, dsu_slot, Split(lp_names, ","));
     }
 
-    SkipMountingPartitions(fstab, false /* verbose */);
-    EnableMandatoryFlags(fstab);
+    SkipMountingPartitions(&fstab, false /* verbose */);
+    EnableMandatoryFlags(&fstab);
 
+    *fstab_out = std::move(fstab);
     return true;
 }
 
@@ -767,31 +780,39 @@
         return true;
     }
 
-    for (const auto& skip_mount_point : Split(skip_config, "\n")) {
-        if (skip_mount_point.empty()) {
+    std::vector<std::string> skip_mount_patterns;
+    for (const auto& line : Split(skip_config, "\n")) {
+        if (line.empty() || StartsWith(line, "#")) {
             continue;
         }
-        auto it = std::remove_if(fstab->begin(), fstab->end(),
-                                 [&skip_mount_point](const auto& entry) {
-                                     return entry.mount_point == skip_mount_point;
-                                 });
-        if (it == fstab->end()) continue;
-        fstab->erase(it, fstab->end());
-        if (verbose) {
-            LINFO << "Skip mounting partition: " << skip_mount_point;
-        }
+        skip_mount_patterns.push_back(line);
     }
 
+    // Returns false if mount_point matches any of the skip mount patterns, so that the FstabEntry
+    // would be partitioned to the second group.
+    auto glob_pattern_mismatch = [&skip_mount_patterns](const FstabEntry& entry) -> bool {
+        for (const auto& pattern : skip_mount_patterns) {
+            if (!fnmatch(pattern.c_str(), entry.mount_point.c_str(), 0 /* flags */)) {
+                return false;
+            }
+        }
+        return true;
+    };
+    auto remove_from = std::stable_partition(fstab->begin(), fstab->end(), glob_pattern_mismatch);
+    if (verbose) {
+        for (auto it = remove_from; it != fstab->end(); ++it) {
+            LINFO << "Skip mounting mountpoint: " << it->mount_point;
+        }
+    }
+    fstab->erase(remove_from, fstab->end());
     return true;
 }
 #endif
 
 // Loads the fstab file and combines with fstab entries passed in from device tree.
 bool ReadDefaultFstab(Fstab* fstab) {
-    Fstab dt_fstab;
-    ReadFstabFromDt(&dt_fstab, false /* verbose */);
-
-    *fstab = std::move(dt_fstab);
+    fstab->clear();
+    ReadFstabFromDt(fstab, false /* verbose */);
 
     std::string default_fstab_path;
     // Use different fstab paths for normal boot and recovery boot, respectively
@@ -802,16 +823,14 @@
     }
 
     Fstab default_fstab;
-    if (!default_fstab_path.empty()) {
-        ReadFstabFromFile(default_fstab_path, &default_fstab);
+    if (!default_fstab_path.empty() && ReadFstabFromFile(default_fstab_path, &default_fstab)) {
+        for (auto&& entry : default_fstab) {
+            fstab->emplace_back(std::move(entry));
+        }
     } else {
         LINFO << __FUNCTION__ << "(): failed to find device default fstab";
     }
 
-    for (auto&& entry : default_fstab) {
-        fstab->emplace_back(std::move(entry));
-    }
-
     return !fstab->empty();
 }
 
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h
new file mode 100644
index 0000000..ac2c787
--- /dev/null
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2021 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.
+//
+
+#pragma once
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <libsnapshot/snapshot_stats.h>
+
+namespace android::snapshot {
+
+class MockSnapshotMergeStats final : public ISnapshotMergeStats {
+  public:
+    virtual ~MockSnapshotMergeStats() = default;
+    // Called when merge starts or resumes.
+    MOCK_METHOD(bool, Start, (), (override));
+    MOCK_METHOD(void, set_state, (android::snapshot::UpdateState, bool), (override));
+    MOCK_METHOD(void, set_cow_file_size, (uint64_t), ());
+    MOCK_METHOD(void, set_total_cow_size_bytes, (uint64_t), (override));
+    MOCK_METHOD(void, set_estimated_cow_size_bytes, (uint64_t), (override));
+    MOCK_METHOD(void, set_boot_complete_time_ms, (uint32_t), (override));
+    MOCK_METHOD(void, set_boot_complete_to_merge_start_time_ms, (uint32_t), (override));
+    MOCK_METHOD(uint64_t, cow_file_size, (), (override));
+    MOCK_METHOD(uint64_t, total_cow_size_bytes, (), (override));
+    MOCK_METHOD(uint64_t, estimated_cow_size_bytes, (), (override));
+    MOCK_METHOD(uint32_t, boot_complete_time_ms, (), (override));
+    MOCK_METHOD(uint32_t, boot_complete_to_merge_start_time_ms, (), (override));
+    MOCK_METHOD(std::unique_ptr<Result>, Finish, (), (override));
+
+    using ISnapshotMergeStats::Result;
+    // Return nullptr if any failure.
+};
+
+}  // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
index 1dab361..280e857 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
@@ -69,6 +69,8 @@
     // must ONLY be called if the control device has already been deleted.
     bool WaitForDeviceDelete(const std::string& control_device);
 
+    void CloseConnection() { sockfd_ = {}; }
+
     // Detach snapuserd. This shuts down the listener socket, and will cause
     // snapuserd to gracefully exit once all handler threads have terminated.
     // This should only be used on first-stage instances of snapuserd.
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 2c5bf75..a0a1e4f 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2297,6 +2297,17 @@
             return false;
         }
     }
+
+    // Terminate the daemon and release the snapuserd_client_ object.
+    // If we need to re-connect with the daemon, EnsureSnapuserdConnected()
+    // will re-create the object and establish the socket connection.
+    if (snapuserd_client_) {
+        LOG(INFO) << "Shutdown snapuserd daemon";
+        snapuserd_client_->DetachSnapuserd();
+        snapuserd_client_->CloseConnection();
+        snapuserd_client_ = nullptr;
+    }
+
     return true;
 }
 
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 6ed0129..8fae00b 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2019,6 +2019,8 @@
 
     // Read bytes back and verify they match the cache.
     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
+
+    ASSERT_TRUE(sm->UnmapAllSnapshots());
 }
 
 TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 0dc8159..c2eb73c 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1200,6 +1200,22 @@
             // emulator specific, should be retired once emulator migrates to
             // androidboot.
             InitPropertySet("ro.boot." + key, value);
+        } else if (key == "android.bootanim" && value == "0") {
+            // emulator specific, should be retired once emulator migrates to
+            // androidboot.
+            InitPropertySet("ro.boot.debug.sf.nobootanimation", "1");
+        } else if (key == "android.checkjni") {
+            // emulator specific, should be retired once emulator migrates to
+            // androidboot.
+            std::string value_bool;
+            if (value == "0") {
+                value_bool = "false";
+            } else if (value == "1") {
+                value_bool = "true";
+            } else {
+                value_bool = value;
+            }
+            InitPropertySet("ro.boot.dalvik.vm.checkjni", value_bool);
         }
     });
 }
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index cab988b..2221228 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -106,10 +106,10 @@
     }
 
     if (std::find_if(external_firmware_handlers->begin(), external_firmware_handlers->end(),
-                     [&args](const auto& other) { return other.devpath == args[2]; }) !=
+                     [&args](const auto& other) { return other.devpath == args[1]; }) !=
         external_firmware_handlers->end()) {
         return Error() << "found a previous external_firmware_handler with the same devpath, '"
-                       << args[2] << "'";
+                       << args[1] << "'";
     }
 
     passwd* pwd = getpwnam(args[2].c_str());
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index b604c53..4e63ba5 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -45,6 +45,13 @@
     EXPECT_EQ(expected.attribute_, test.attribute_);
 }
 
+void TestExternalFirmwareHandler(const ExternalFirmwareHandler& expected,
+                                 const ExternalFirmwareHandler& test) {
+    EXPECT_EQ(expected.devpath, test.devpath) << expected.devpath;
+    EXPECT_EQ(expected.uid, test.uid) << expected.uid;
+    EXPECT_EQ(expected.handler_path, test.handler_path) << expected.handler_path;
+}
+
 template <typename T, typename F>
 void TestVector(const T& expected, const T& test, F function) {
     ASSERT_EQ(expected.size(), test.size());
@@ -67,6 +74,8 @@
     TestVector(expected.sysfs_permissions, result.sysfs_permissions, TestSysfsPermissions);
     TestVector(expected.dev_permissions, result.dev_permissions, TestPermissions);
     EXPECT_EQ(expected.firmware_directories, result.firmware_directories);
+    TestVector(expected.external_firmware_handlers, result.external_firmware_handlers,
+               TestExternalFirmwareHandler);
 }
 
 TEST(ueventd_parser, EmptyFile) {
@@ -144,7 +153,7 @@
     auto ueventd_file = R"(
 external_firmware_handler devpath root handler_path
 external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
-external_firmware_handler /devices/path/firmware/something001.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
+external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
 )";
 
     auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
@@ -159,7 +168,7 @@
                     "/vendor/bin/firmware_handler.sh",
             },
             {
-                    "/devices/path/firmware/something001.bin",
+                    "/devices/path/firmware/something002.bin",
                     AID_RADIO,
                     "/vendor/bin/firmware_handler.sh --has --arguments",
             },
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 3660199..354c7b3 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -14,6 +14,10 @@
 // limitations under the License.
 //
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 rust_bindgen {
     name: "libstatspull_bindgen",
     wrapper_src: "statslog.h",
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index dcc469e..93f9654 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -242,12 +242,12 @@
 }
 
 TEST(RefBase, AssertWeakRefExistsSuccess) {
-    // uses some other refcounting method, or non at all
     bool isDeleted;
     sp<Foo> foo = sp<Foo>::make(&isDeleted);
     wp<Foo> weakFoo = foo;
 
     EXPECT_EQ(weakFoo, wp<Foo>::fromExisting(foo.get()));
+    EXPECT_EQ(weakFoo.unsafe_get(), wp<Foo>::fromExisting(foo.get()).unsafe_get());
 
     EXPECT_FALSE(isDeleted);
     foo = nullptr;
@@ -255,7 +255,7 @@
 }
 
 TEST(RefBase, AssertWeakRefExistsDeath) {
-    // uses some other refcounting method, or non at all
+    // uses some other refcounting method, or none at all
     bool isDeleted;
     Foo* foo = new Foo(&isDeleted);
 
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 5a5bd56..7148949 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -547,6 +547,7 @@
     refs->incWeakRequireWeak(other);
 
     wp<T> ret;
+    ret.m_ptr = other;
     ret.m_refs = refs;
     return ret;
 }
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 1f07052..dd53b9e 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -72,6 +72,12 @@
     template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
     template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
 
+    // Cast a strong pointer directly from one type to another. Constructors
+    // allow changing types, but only if they are pointer-compatible. This does
+    // a static_cast internally.
+    template <typename U>
+    static inline sp<T> cast(const sp<U>& other);
+
     ~sp();
 
     // Assignment
@@ -279,6 +285,12 @@
     other.m_ptr = nullptr;
 }
 
+template <typename T>
+template <typename U>
+sp<T> sp<T>::cast(const sp<U>& other) {
+    return sp<T>::fromExisting(static_cast<T*>(other.get()));
+}
+
 template<typename T>
 sp<T>::~sp() {
     if (m_ptr)