Merge "libdexfile_external is replaced by libdexfile (reland)."
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 700d4bd..dfed77e 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -673,7 +673,7 @@
     return fd;
 }
 
-static void CheckRequirement(const std::string& cur_product, const std::string& var,
+static bool CheckRequirement(const std::string& cur_product, const std::string& var,
                              const std::string& product, bool invert,
                              const std::vector<std::string>& options) {
     Status("Checking '" + var + "'");
@@ -685,7 +685,7 @@
             double split = now();
             fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n",
                     cur_product.c_str(), product.c_str(), (split - start));
-            return;
+            return true;
         }
     }
 
@@ -694,7 +694,7 @@
         fprintf(stderr, "FAILED\n\n");
         fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(),
                 fb->Error().c_str());
-        die("requirements not met!");
+        return false;
     }
 
     bool match = false;
@@ -714,7 +714,7 @@
     if (match) {
         double split = now();
         fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
-        return;
+        return true;
     }
 
     fprintf(stderr, "FAILED\n\n");
@@ -724,7 +724,7 @@
         fprintf(stderr, " or '%s'", it->c_str());
     }
     fprintf(stderr, ".\n\n");
-    die("requirements not met!");
+    return false;
 }
 
 bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product,
@@ -788,7 +788,7 @@
     }
 }
 
-static void CheckRequirements(const std::string& data) {
+static void CheckRequirements(const std::string& data, bool force_flash) {
     std::string cur_product;
     if (fb->GetVar("product", &cur_product) != fastboot::SUCCESS) {
         fprintf(stderr, "getvar:product FAILED (%s)\n", fb->Error().c_str());
@@ -812,7 +812,14 @@
         if (name == "partition-exists") {
             HandlePartitionExists(options);
         } else {
-            CheckRequirement(cur_product, name, product, invert, options);
+            bool met = CheckRequirement(cur_product, name, product, invert, options);
+            if (!met) {
+                if (!force_flash) {
+                  die("requirements not met!");
+                } else {
+                  fprintf(stderr, "requirements not met! but proceeding due to --force\n");
+                }
+            }
         }
     }
 }
@@ -1405,7 +1412,8 @@
 
 class FlashAllTool {
   public:
-    FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary, bool wipe);
+    FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary,
+                 bool wipe, bool force_flash);
 
     void Flash();
 
@@ -1421,16 +1429,19 @@
     std::string slot_override_;
     bool skip_secondary_;
     bool wipe_;
+    bool force_flash_;
     std::string secondary_slot_;
     std::vector<std::pair<const Image*, std::string>> boot_images_;
     std::vector<std::pair<const Image*, std::string>> os_images_;
 };
 
-FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary, bool wipe)
+FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
+                           bool skip_secondary, bool wipe, bool force_flash)
    : source_(source),
      slot_override_(slot_override),
      skip_secondary_(skip_secondary),
-     wipe_(wipe)
+     wipe_(wipe),
+     force_flash_(force_flash)
 {
 }
 
@@ -1478,7 +1489,7 @@
     if (!source_.ReadFile("android-info.txt", &contents)) {
         die("could not read android-info.txt");
     }
-    ::CheckRequirements({contents.data(), contents.size()});
+    ::CheckRequirements({contents.data(), contents.size()}, force_flash_);
 }
 
 void FlashAllTool::DetermineSecondarySlot() {
@@ -1598,14 +1609,15 @@
     return unzip_to_file(zip_, name.c_str());
 }
 
-static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) {
+static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary,
+                      bool force_flash) {
     ZipArchiveHandle zip;
     int error = OpenArchive(filename, &zip);
     if (error != 0) {
         die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
     }
 
-    FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false);
+    FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false, force_flash);
     tool.Flash();
 
     CloseArchive(zip);
@@ -1630,8 +1642,9 @@
     return unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
 }
 
-static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
-    FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe);
+static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe,
+                        bool force_flash) {
+    FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe, force_flash);
     tool.Flash();
 }
 
@@ -2179,9 +2192,9 @@
         } else if (command == "flashall") {
             if (slot_override == "all") {
                 fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
-                do_flashall(slot_override, true, wants_wipe);
+                do_flashall(slot_override, true, wants_wipe, force_flash);
             } else {
-                do_flashall(slot_override, skip_secondary, wants_wipe);
+                do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
             }
             wants_reboot = true;
         } else if (command == "update") {
@@ -2193,7 +2206,7 @@
             if (!args.empty()) {
                 filename = next_arg(&args);
             }
-            do_update(filename.c_str(), slot_override, skip_secondary || slot_all);
+            do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash);
             wants_reboot = true;
         } else if (command == FB_CMD_SET_ACTIVE) {
             std::string slot = verify_slot(next_arg(&args), false);
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 950fc96..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>
@@ -779,21 +780,31 @@
         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
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/String16.cpp b/libutils/String16.cpp
index 70bf5a0..e3e5f11 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -390,28 +390,6 @@
     return static_cast<size_t>(*(p - 1));
 }
 
-status_t String16::makeLower()
-{
-    const size_t N = size();
-    const char16_t* str = string();
-    char16_t* edited = nullptr;
-    for (size_t i=0; i<N; i++) {
-        const char16_t v = str[i];
-        if (v >= 'A' && v <= 'Z') {
-            if (!edited) {
-                SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
-                if (!buf) {
-                    return NO_MEMORY;
-                }
-                edited = (char16_t*)buf->data();
-                mString = str = edited;
-            }
-            edited[i] = tolower((char)v);
-        }
-    }
-    return OK;
-}
-
 status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
 {
     const size_t N = size();
diff --git a/libutils/String16_fuzz.cpp b/libutils/String16_fuzz.cpp
index 63c2800..defa0f5 100644
--- a/libutils/String16_fuzz.cpp
+++ b/libutils/String16_fuzz.cpp
@@ -34,11 +34,6 @@
                     str1.size();
                 }),
 
-                // Casing
-                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
-                    str1.makeLower();
-                }),
-
                 // Comparison
                 ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                     str1.startsWith(str2);
diff --git a/libutils/String16_test.cpp b/libutils/String16_test.cpp
index 2505f44..c2e9b02 100644
--- a/libutils/String16_test.cpp
+++ b/libutils/String16_test.cpp
@@ -97,13 +97,6 @@
     EXPECT_STR16EQ(u" m", tmp);
 }
 
-TEST(String16Test, MakeLower) {
-    String16 tmp("Verify Me!");
-    tmp.makeLower();
-    EXPECT_EQ(10U, tmp.size());
-    EXPECT_STR16EQ(u"verify me!", tmp);
-}
-
 TEST(String16Test, ReplaceAll) {
     String16 tmp("Verify verify Verify");
     tmp.replaceAll(u'r', u'!');
@@ -176,14 +169,6 @@
     EXPECT_FALSE(tmp.isStaticString());
 }
 
-TEST(String16Test, StaticStringMakeLower) {
-    StaticString16 tmp(u"Verify me!");
-    tmp.makeLower();
-    EXPECT_EQ(10U, tmp.size());
-    EXPECT_STR16EQ(u"verify me!", tmp);
-    EXPECT_FALSE(tmp.isStaticString());
-}
-
 TEST(String16Test, StaticStringReplaceAll) {
     StaticString16 tmp(u"Verify verify Verify");
     tmp.replaceAll(u'r', u'!');
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/String16.h b/libutils/include/utils/String16.h
index 1a4b47e..5ce48c6 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -85,8 +85,6 @@
 
             bool                contains(const char16_t* chrs) const;
 
-            status_t            makeLower();
-
             status_t            replaceAll(char16_t replaceThis,
                                            char16_t withThis);
 
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)