Merge "Snap for 7562097 from a2aba786fefb62f14bf3e6d4b6552dda78857445 to sdk-release" into sdk-release
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 8314ec5..541f254 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -684,13 +684,9 @@
 TEST(libdm, CreateEmptyDevice) {
     DeviceMapper& dm = DeviceMapper::Instance();
     ASSERT_TRUE(dm.CreateEmptyDevice("empty-device"));
-    auto guard = android::base::make_scope_guard([&]() { dm.DeleteDevice("empty-device", 5s); });
+    auto guard =
+            android::base::make_scope_guard([&]() { dm.DeleteDeviceIfExists("empty-device", 5s); });
 
     // Empty device should be in suspended state.
     ASSERT_EQ(DmDeviceState::SUSPENDED, dm.GetState("empty-device"));
-
-    std::string path;
-    ASSERT_TRUE(dm.WaitForDevice("empty-device", 5s, &path));
-    // Path should exist.
-    ASSERT_EQ(0, access(path.c_str(), F_OK));
 }
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index b3198a0..af49c7d 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -381,10 +381,10 @@
     std::set<int, std::greater<int>> other_ops;
     auto seq_ops_set = std::unordered_set<uint32_t>();
     auto block_map = std::make_shared<std::unordered_map<uint32_t, int>>();
-    int num_seqs = 0;
+    size_t num_seqs = 0;
     size_t read;
 
-    for (int i = 0; i < ops_->size(); i++) {
+    for (size_t i = 0; i < ops_->size(); i++) {
         auto& current_op = ops_->data()[i];
 
         if (current_op.type == kCowSequenceOp) {
@@ -396,7 +396,7 @@
                 PLOG(ERROR) << "Failed to read sequence op!";
                 return false;
             }
-            for (int j = num_seqs; j < num_seqs + seq_len; j++) {
+            for (size_t j = num_seqs; j < num_seqs + seq_len; j++) {
                 seq_ops_set.insert(merge_op_blocks->data()[j]);
             }
             num_seqs += seq_len;
@@ -413,10 +413,11 @@
         }
         block_map->insert({current_op.new_block, i});
     }
-    if (merge_op_blocks->size() > header_.num_merge_ops)
+    if (merge_op_blocks->size() > header_.num_merge_ops) {
         num_ordered_ops_to_merge_ = merge_op_blocks->size() - header_.num_merge_ops;
-    else
+    } else {
         num_ordered_ops_to_merge_ = 0;
+    }
     merge_op_blocks->reserve(merge_op_blocks->size() + other_ops.size());
     for (auto block : other_ops) {
         merge_op_blocks->emplace_back(block);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 05f7066..6c3059c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -126,6 +126,10 @@
 
     bool GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read);
 
+    // Returns the total number of data ops that should be merged. This is the
+    // count of the merge sequence before removing already-merged operations.
+    // It may be different than the actual data op count, for example, if there
+    // are duplicate ops in the stream.
     uint64_t get_num_total_data_ops() { return num_total_data_ops_; }
 
     uint64_t get_num_ordered_ops_to_merge() { return num_ordered_ops_to_merge_; }
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 0e36da1..bed5f56 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1193,11 +1193,7 @@
             return MergeFailureCode::ParseCowConsistencyCheck;
         }
 
-        for (auto iter = reader.GetOpIter(); !iter->Done(); iter->Next()) {
-            if (!IsMetadataOp(iter->Get())) {
-                num_ops++;
-            }
-        }
+        num_ops = reader.get_num_total_data_ops();
     }
 
     // Second pass, try as hard as we can to get the actual number of blocks
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 6018643..b2203fe 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -1184,6 +1184,53 @@
     }
 }
 
+TEST_F(SnapshotUpdateTest, DuplicateOps) {
+    if (!IsCompressionEnabled()) {
+        GTEST_SKIP() << "Compression-only test";
+    }
+
+    // OTA client blindly unmaps all partitions that are possibly mapped.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
+    }
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name));
+    }
+
+    std::vector<PartitionUpdate*> partitions = {sys_, vnd_, prd_};
+    for (auto* partition : partitions) {
+        AddOperation(partition);
+
+        std::unique_ptr<ISnapshotWriter> writer;
+        auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer);
+        ASSERT_TRUE(res);
+        ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
+        ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
+        ASSERT_TRUE(writer->Finalize());
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = NewManagerForFirstStageMount("_b");
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
+
+    // Initiate the merge and wait for it to be completed.
+    ASSERT_TRUE(init->InitiateMerge());
+    ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
+}
+
 // Test that shrinking and growing partitions at the same time is handled
 // correctly in VABC.
 TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index e578a76..a09b111 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -64,7 +64,7 @@
 
     int ret = msync(mapped_addr_, BLOCK_SZ, MS_SYNC);
     if (ret < 0) {
-        PLOG(ERROR) << "msync header failed: " << ret;
+        SNAP_PLOG(ERROR) << "msync header failed: " << ret;
         return false;
     }
 
diff --git a/init/Android.bp b/init/Android.bp
index 46fa1f6..3e8d4e3 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -257,7 +257,7 @@
     name: "init_first_stage_cc_defaults",
     module_type: "cc_defaults",
     config_namespace: "ANDROID",
-    bool_variables: ["BOARD_BUILD_SYSTEM_ROOT_IMAGE"],
+    bool_variables: ["BOARD_BUILD_SYSTEM_ROOT_IMAGE", "BOARD_USES_RECOVERY_AS_BOOT"],
     properties: ["installable"],
 }
 
@@ -269,6 +269,9 @@
         BOARD_BUILD_SYSTEM_ROOT_IMAGE: {
             installable: false,
         },
+        BOARD_USES_RECOVERY_AS_BOOT: {
+            installable: false,
+        },
     },
 }
 
diff --git a/init/Android.mk b/init/Android.mk
index c1b0cf9..c08fe03 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -9,8 +9,10 @@
 LOCAL_LICENSE_CONDITIONS := notice
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
 LOCAL_REQUIRED_MODULES := \
    init_first_stage \
 
+endif  # BOARD_USES_RECOVERY_AS_BOOT
 endif  # BOARD_BUILD_SYSTEM_ROOT_IMAGE
 include $(BUILD_PHONY_PACKAGE)
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 8511da9..195e122 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -429,17 +429,24 @@
 // ---------------------------------------------------------------------------
 // Path functions
 
-static void setPathName(String8& s, const char* name) {
-    size_t len = strlen(name);
-    char* buf = s.lockBuffer(len);
+void String8::setPathName(const char* name)
+{
+    setPathName(name, strlen(name));
+}
+
+void String8::setPathName(const char* name, size_t len)
+{
+    char* buf = lockBuffer(len);
 
     memcpy(buf, name, len);
 
     // remove trailing path separator, if present
-    if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--;
+    if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
+        len--;
+
     buf[len] = '\0';
 
-    s.unlockBuffer(len);
+    unlockBuffer(len);
 }
 
 String8 String8::getPathLeaf(void) const
@@ -552,7 +559,7 @@
         size_t len = length();
         if (len == 0) {
             // no existing filename, just use the new one
-            setPathName(*this, name);
+            setPathName(name);
             return *this;
         }
 
@@ -572,7 +579,7 @@
 
         return *this;
     } else {
-        setPathName(*this, name);
+        setPathName(name);
         return *this;
     }
 }
diff --git a/libutils/String8_fuzz.cpp b/libutils/String8_fuzz.cpp
index faf49b6..a45d675 100644
--- a/libutils/String8_fuzz.cpp
+++ b/libutils/String8_fuzz.cpp
@@ -91,6 +91,10 @@
                 },
                 [](FuzzedDataProvider* dataProvider, android::String8* str1,
                    android::String8*) -> void {
+                    str1->setPathName(dataProvider->ConsumeBytesWithTerminator<char>(5).data());
+                },
+                [](FuzzedDataProvider* dataProvider, android::String8* str1,
+                   android::String8*) -> void {
                     str1->appendPath(dataProvider->ConsumeBytesWithTerminator<char>(5).data());
                 },
 };
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index 8b2dcf9..cee5dc6 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -137,6 +137,14 @@
      */
 
     /*
+     * Set the filename field to a specific value.
+     *
+     * Normalizes the filename, removing a trailing '/' if present.
+     */
+    void setPathName(const char* name);
+    void setPathName(const char* name, size_t numChars);
+
+    /*
      * Get just the filename component.
      *
      * "/tmp/foo/bar.c" --> "bar.c"
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index aa610e7..ff6460d 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -129,6 +129,27 @@
     src: "set_attestation_key/keymaster_soft_attestation_keys.xml",
 }
 
+cc_library {
+    name: "libtrusty_ipc",
+    vendor: true,
+    srcs: ["ipc/trusty_keymaster_ipc.cpp"],
+    local_include_dirs: ["include"],
+    shared_libs: [
+        "libc",
+        "libcrypto",
+        "liblog",
+        "libtrusty",
+        "libhardware",
+        "libkeymaster_messages",
+        "libxml2",
+    ],
+    export_include_dirs: ["include"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
 cc_binary {
     name: "trusty_keymaster_set_attestation_key",
     vendor: true,
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index 6f4713b..17fee15 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -71,6 +71,7 @@
     KM_SET_PRODUCT_ID = (0x9000 << KEYMASTER_REQ_SHIFT),
     KM_CLEAR_ATTESTATION_CERT_CHAIN = (0xa000 << KEYMASTER_REQ_SHIFT),
     KM_SET_WRAPPED_ATTESTATION_KEY = (0xb000 << KEYMASTER_REQ_SHIFT),
+    KM_SET_ATTESTATION_IDS = (0xc000 << KEYMASTER_REQ_SHIFT)
 };
 
 #ifdef __ANDROID__
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index a471435..d67089f 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -29,7 +29,10 @@
         "proxy.c",
     ],
 
-    shared_libs: ["liblog"],
+    shared_libs: [
+        "liblog",
+        "libhardware_legacy",
+    ],
     header_libs: ["libcutils_headers"],
 
     static_libs: [
diff --git a/trusty/storage/proxy/rpmb.c b/trusty/storage/proxy/rpmb.c
index d1ed649..b59fb67 100644
--- a/trusty/storage/proxy/rpmb.c
+++ b/trusty/storage/proxy/rpmb.c
@@ -29,6 +29,8 @@
 #include <linux/major.h>
 #include <linux/mmc/ioctl.h>
 
+#include <hardware_legacy/power.h>
+
 #include "ipc.h"
 #include "log.h"
 #include "rpmb.h"
@@ -100,6 +102,8 @@
 static uint8_t read_buf[4096];
 static enum dev_type dev_type = UNKNOWN_RPMB;
 
+static const char* UFS_WAKE_LOCK_NAME = "ufs_seq_wakelock";
+
 #ifdef RPMB_DEBUG
 
 static void print_buf(const char* prefix, const uint8_t* buf, size_t size) {
@@ -194,6 +198,7 @@
 
 static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req) {
     int rc;
+    int wl_rc;
     const uint8_t* write_buf = req->payload;
     /*
      * Meaning of member values are stated on the definition of struct sec_proto_cdb.
@@ -202,6 +207,12 @@
     struct sec_proto_cdb out_cdb = {0xB5, 0xEC, 0x00, 0x01, 0x00, 0x00, 0, 0x00, 0x00};
     unsigned char sense_buffer[32];
 
+    wl_rc = acquire_wake_lock(PARTIAL_WAKE_LOCK, UFS_WAKE_LOCK_NAME);
+    if (wl_rc < 0) {
+        ALOGE("%s: failed to acquire wakelock: %d, %s\n", __func__, wl_rc, strerror(errno));
+        return wl_rc;
+    }
+
     if (req->reliable_write_size) {
         /* Prepare SECURITY PROTOCOL OUT command. */
         out_cdb.length = __builtin_bswap32(req->reliable_write_size);
@@ -212,6 +223,7 @@
         rc = ioctl(sg_fd, SG_IO, &io_hdr);
         if (rc < 0) {
             ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+            goto err_op;
         }
         write_buf += req->reliable_write_size;
     }
@@ -225,6 +237,7 @@
         rc = ioctl(sg_fd, SG_IO, &io_hdr);
         if (rc < 0) {
             ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+            goto err_op;
         }
         write_buf += req->write_size;
     }
@@ -240,6 +253,13 @@
             ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
         }
     }
+
+err_op:
+    wl_rc = release_wake_lock(UFS_WAKE_LOCK_NAME);
+    if (wl_rc < 0) {
+        ALOGE("%s: failed to release wakelock: %d, %s\n", __func__, wl_rc, strerror(errno));
+    }
+
     return rc;
 }