Merge "Split init's source files init first stage and second stage"
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 3fb14f3..da273fd 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1925,7 +1925,8 @@
     for (int i = argc - 1; i >= 0; i--) {
         const char* file = argv[i];
 
-        if (android::base::EndsWithIgnoreCase(file, ".apk")) {
+        if (android::base::EndsWithIgnoreCase(file, ".apk") ||
+            android::base::EndsWithIgnoreCase(file, ".dm")) {
             struct stat sb;
             if (stat(file, &sb) != -1) total_size += sb.st_size;
             first_apk = i;
@@ -1986,9 +1987,8 @@
         }
 
         std::string cmd = android::base::StringPrintf(
-                "%s install-write -S %" PRIu64 " %d %d_%s -",
-                install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, i,
-                android::base::Basename(file).c_str());
+            "%s install-write -S %" PRIu64 " %d %s -", install_cmd.c_str(),
+            static_cast<uint64_t>(sb.st_size), session_id, android::base::Basename(file).c_str());
 
         int localFd = adb_open(file, O_RDONLY);
         if (localFd < 0) {
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index 05e03e1..aa68ceb 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -133,7 +133,11 @@
 
 bool DestroyLogicalPartition(const std::string& name) {
     DeviceMapper& dm = DeviceMapper::Instance();
-    return dm.DeleteDevice(name);
+    if (!dm.DeleteDevice(name)) {
+        return false;
+    }
+    LINFO << "Unmapped logical partition " << name;
+    return true;
 }
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index eb429b9..2015e4d 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -84,6 +84,19 @@
 
 void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
     size_ += extent->num_sectors() * LP_SECTOR_SIZE;
+
+    if (LinearExtent* new_extent = extent->AsLinearExtent()) {
+        if (!extents_.empty() && extents_.back()->AsLinearExtent() &&
+            extents_.back()->AsLinearExtent()->end_sector() == new_extent->physical_sector()) {
+            // If the previous extent can be merged into this new one, do so
+            // to avoid creating unnecessary extents.
+            LinearExtent* prev_extent = extents_.back()->AsLinearExtent();
+            extent = std::make_unique<LinearExtent>(
+                    prev_extent->num_sectors() + new_extent->num_sectors(),
+                    prev_extent->physical_sector());
+            extents_.pop_back();
+        }
+    }
     extents_.push_back(std::move(extent));
 }
 
@@ -498,13 +511,18 @@
 bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
     // Align the space needed up to the nearest sector.
     uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size);
+    uint64_t old_size = partition->size();
 
-    if (aligned_size > partition->size()) {
-        return GrowPartition(partition, aligned_size);
-    }
-    if (aligned_size < partition->size()) {
+    if (aligned_size > old_size) {
+        if (!GrowPartition(partition, aligned_size)) {
+            return false;
+        }
+    } else if (aligned_size < partition->size()) {
         ShrinkPartition(partition, aligned_size);
     }
+
+    LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to "
+          << aligned_size << " bytes";
     return true;
 }
 
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index f1a91c4..da9c8f3 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -69,6 +69,11 @@
     EXPECT_EQ(system->size(), 131072);
     EXPECT_EQ(system->extents().size(), 1);
     EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE);
+    // Test resizing again, that the extents are merged together.
+    builder->ResizePartition(system, 1024 * 256);
+    EXPECT_EQ(system->size(), 1024 * 256);
+    EXPECT_EQ(system->extents().size(), 1);
+    EXPECT_EQ(system->extents()[0]->num_sectors(), (1024 * 256) / LP_SECTOR_SIZE);
 
     // Test shrinking within the same extent.
     builder->ResizePartition(system, 32768);
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index e83b922..a35cf8e 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -81,6 +81,7 @@
     LinearExtent* AsLinearExtent() override { return this; }
 
     uint64_t physical_sector() const { return physical_sector_; }
+    uint64_t end_sector() const { return physical_sector_ + num_sectors_; }
 
   private:
     uint64_t physical_sector_;
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 4522275..6ef5124 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -26,6 +26,8 @@
 #include "liblp/metadata_format.h"
 
 #define LP_TAG "[liblp]"
+#define LWARN LOG(WARNING) << LP_TAG
+#define LINFO LOG(INFO) << LP_TAG
 #define LERROR LOG(ERROR) << LP_TAG
 #define PERROR PLOG(ERROR) << LP_TAG
 
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 156319b..fc9d83f 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -304,7 +304,11 @@
         PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
         return false;
     }
-    return FlashPartitionTable(fd, metadata, slot_number);
+    if (!FlashPartitionTable(fd, metadata, slot_number)) {
+        return false;
+    }
+    LWARN << "Flashed new logical partition geometry to " << block_device;
+    return true;
 }
 
 bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
@@ -314,7 +318,12 @@
         PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
         return false;
     }
-    return UpdatePartitionTable(fd, metadata, slot_number);
+    if (!UpdatePartitionTable(fd, metadata, slot_number)) {
+        return false;
+    }
+    LINFO << "Updated logical partition table at slot " << slot_number << " on device "
+          << block_device;
+    return true;
 }
 
 bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index df5da65..be2145d 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -190,6 +190,7 @@
         "tests/MemoryRangeTest.cpp",
         "tests/MemoryRemoteTest.cpp",
         "tests/MemoryTest.cpp",
+        "tests/RegsInfoTest.cpp",
         "tests/RegsIterateTest.cpp",
         "tests/RegsStepIfSignalHandlerTest.cpp",
         "tests/RegsTest.cpp",
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index 47825f5..e6dd33c 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -25,11 +25,13 @@
 
 template <typename AddressType>
 struct RegsInfo {
+  static constexpr size_t MAX_REGISTERS = 64;
+
   RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
 
   RegsImpl<AddressType>* regs = nullptr;
   uint64_t saved_reg_map = 0;
-  AddressType saved_regs[64];
+  AddressType saved_regs[MAX_REGISTERS];
 
   inline AddressType Get(uint32_t reg) {
     if (IsSaved(reg)) {
@@ -39,23 +41,23 @@
   }
 
   inline AddressType* Save(uint32_t reg) {
-    if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
-      // This should never happen as since all currently supported
-      // architectures have the total number of registers < 64.
+    if (reg > MAX_REGISTERS) {
+      // This should never happen since all currently supported
+      // architectures have < 64 total registers.
       abort();
     }
-    saved_reg_map |= 1 << reg;
+    saved_reg_map |= 1ULL << reg;
     saved_regs[reg] = (*regs)[reg];
     return &(*regs)[reg];
   }
 
   inline bool IsSaved(uint32_t reg) {
-    if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
-      // This should never happen as since all currently supported
-      // architectures have the total number of registers < 64.
+    if (reg > MAX_REGISTERS) {
+      // This should never happen since all currently supported
+      // architectures have < 64 total registers.
       abort();
     }
-    return saved_reg_map & (1 << reg);
+    return saved_reg_map & (1ULL << reg);
   }
 
   inline uint16_t Total() { return regs->total_regs(); }
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
new file mode 100644
index 0000000..052b5bf
--- /dev/null
+++ b/libunwindstack/tests/RegsInfoTest.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Regs.h>
+
+#include "RegsFake.h"
+#include "RegsInfo.h"
+
+namespace unwindstack {
+
+TEST(RegsInfoTest, single_uint32_t) {
+  RegsImplFake<uint32_t> regs(10);
+  RegsInfo<uint32_t> info(&regs);
+
+  regs[1] = 0x100;
+  ASSERT_FALSE(info.IsSaved(1));
+  ASSERT_EQ(0x100U, info.Get(1));
+  ASSERT_EQ(10, info.Total());
+
+  uint32_t* value = info.Save(1);
+  ASSERT_EQ(value, &regs[1]);
+  regs[1] = 0x200;
+  ASSERT_TRUE(info.IsSaved(1));
+  ASSERT_EQ(0x100U, info.Get(1));
+  ASSERT_EQ(0x200U, regs[1]);
+}
+
+TEST(RegsInfoTest, single_uint64_t) {
+  RegsImplFake<uint64_t> regs(20);
+  RegsInfo<uint64_t> info(&regs);
+
+  regs[3] = 0x300;
+  ASSERT_FALSE(info.IsSaved(3));
+  ASSERT_EQ(0x300U, info.Get(3));
+  ASSERT_EQ(20, info.Total());
+
+  uint64_t* value = info.Save(3);
+  ASSERT_EQ(value, &regs[3]);
+  regs[3] = 0x400;
+  ASSERT_TRUE(info.IsSaved(3));
+  ASSERT_EQ(0x300U, info.Get(3));
+  ASSERT_EQ(0x400U, regs[3]);
+}
+
+TEST(RegsInfoTest, all) {
+  RegsImplFake<uint64_t> regs(64);
+  RegsInfo<uint64_t> info(&regs);
+
+  for (uint32_t i = 0; i < 64; i++) {
+    regs[i] = i * 0x100;
+    ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+  }
+
+  for (uint32_t i = 0; i < 64; i++) {
+    ASSERT_FALSE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+    uint64_t* reg = info.Save(i);
+    ASSERT_EQ(reg, &regs[i]) << "Reg " + std::to_string(i) + " failed.";
+    *reg = i * 0x1000 + 0x100;
+    ASSERT_EQ(i * 0x1000 + 0x100, regs[i]) << "Reg " + std::to_string(i) + " failed.";
+  }
+
+  for (uint32_t i = 0; i < 64; i++) {
+    ASSERT_TRUE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+    ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+  }
+}
+
+}  // namespace unwindstack