Reject update if static partition is a super block device.

If the static partition is currently used as a super block
device, do not write to it.

Test: manual OTA

Change-Id: I167cfccf7d9df7d09ab633c8928697b57d3b314b
diff --git a/boot_control_android.cc b/boot_control_android.cc
index b99554c..f4e0a4b 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -105,25 +105,31 @@
   return true;
 }
 
-namespace {
+bool BootControlAndroid::IsSuperBlockDevice(
+    const base::FilePath& device_dir,
+    Slot slot,
+    const string& partition_name_suffix) const {
+  string source_device =
+      device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
+  auto source_metadata = dynamic_control_->LoadMetadataBuilder(
+      source_device, slot, BootControlInterface::kInvalidSlot);
+  return source_metadata->HasBlockDevice(partition_name_suffix);
+}
 
-enum class DynamicPartitionDeviceStatus {
-  SUCCESS,
-  ERROR,
-  TRY_STATIC,
-};
-
-DynamicPartitionDeviceStatus GetDynamicPartitionDevice(
-    DynamicPartitionControlInterface* dynamic_control,
-    const string& super_device,
+BootControlAndroid::DynamicPartitionDeviceStatus
+BootControlAndroid::GetDynamicPartitionDevice(
+    const base::FilePath& device_dir,
     const string& partition_name_suffix,
     Slot slot,
-    string* device) {
-  if (!dynamic_control->IsDynamicPartitionsEnabled()) {
+    string* device) const {
+  if (!dynamic_control_->IsDynamicPartitionsEnabled()) {
     return DynamicPartitionDeviceStatus::TRY_STATIC;
   }
 
-  auto builder = dynamic_control->LoadMetadataBuilder(
+  string super_device =
+      device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
+
+  auto builder = dynamic_control_->LoadMetadataBuilder(
       super_device, slot, BootControlInterface::kInvalidSlot);
 
   if (builder == nullptr) {
@@ -135,13 +141,25 @@
   if (builder->FindPartition(partition_name_suffix) == nullptr) {
     LOG(INFO) << partition_name_suffix
               << " is not in super partition metadata.";
+
+    Slot current_slot = GetCurrentSlot();
+    if (IsSuperBlockDevice(device_dir, current_slot, partition_name_suffix)) {
+      LOG(ERROR) << "The static partition " << partition_name_suffix
+                 << " is a block device for current metadata ("
+                 << fs_mgr_get_super_partition_name(current_slot) << ", slot "
+                 << BootControlInterface::SlotName(current_slot)
+                 << "). It cannot be used as a logical partition.";
+      return DynamicPartitionDeviceStatus::ERROR;
+    }
+
     return DynamicPartitionDeviceStatus::TRY_STATIC;
   }
 
-  DmDeviceState state = dynamic_control->GetState(partition_name_suffix);
+  DmDeviceState state = dynamic_control_->GetState(partition_name_suffix);
 
   if (state == DmDeviceState::ACTIVE) {
-    if (dynamic_control->GetDmDevicePathByName(partition_name_suffix, device)) {
+    if (dynamic_control_->GetDmDevicePathByName(partition_name_suffix,
+                                                device)) {
       LOG(INFO) << partition_name_suffix
                 << " is mapped on device mapper: " << *device;
       return DynamicPartitionDeviceStatus::SUCCESS;
@@ -156,11 +174,11 @@
   // Hence, if it is not mapped, we assume it is a source partition and
   // map it without force_writable.
   if (state == DmDeviceState::INVALID) {
-    if (dynamic_control->MapPartitionOnDeviceMapper(super_device,
-                                                    partition_name_suffix,
-                                                    slot,
-                                                    false /* force_writable */,
-                                                    device)) {
+    if (dynamic_control_->MapPartitionOnDeviceMapper(super_device,
+                                                     partition_name_suffix,
+                                                     slot,
+                                                     false /* force_writable */,
+                                                     device)) {
       return DynamicPartitionDeviceStatus::SUCCESS;
     }
     return DynamicPartitionDeviceStatus::ERROR;
@@ -171,7 +189,6 @@
              << static_cast<std::underlying_type_t<DmDeviceState>>(state);
   return DynamicPartitionDeviceStatus::ERROR;
 }
-}  // namespace
 
 bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
                                             Slot slot,
@@ -188,13 +205,8 @@
   }
   base::FilePath device_dir(device_dir_str);
 
-  string super_device =
-      device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
-  switch (GetDynamicPartitionDevice(dynamic_control_.get(),
-                                    super_device,
-                                    partition_name_suffix,
-                                    slot,
-                                    device)) {
+  switch (GetDynamicPartitionDevice(
+      device_dir, partition_name_suffix, slot, device)) {
     case DynamicPartitionDeviceStatus::SUCCESS:
       return true;
     case DynamicPartitionDeviceStatus::TRY_STATIC:
diff --git a/boot_control_android.h b/boot_control_android.h
index d831273..d6590fb 100644
--- a/boot_control_android.h
+++ b/boot_control_android.h
@@ -64,6 +64,24 @@
   // Wrapper method of IBootControl::getSuffix().
   bool GetSuffix(Slot slot, std::string* out) const;
 
+  enum class DynamicPartitionDeviceStatus {
+    SUCCESS,
+    ERROR,
+    TRY_STATIC,
+  };
+
+  DynamicPartitionDeviceStatus GetDynamicPartitionDevice(
+      const base::FilePath& device_dir,
+      const std::string& partition_name_suffix,
+      Slot slot,
+      std::string* device) const;
+
+  // Return true if |partition_name_suffix| is a block device of
+  // super partition metadata slot |slot|.
+  bool IsSuperBlockDevice(const base::FilePath& device_dir,
+                          Slot slot,
+                          const std::string& partition_name_suffix) const;
+
   DISALLOW_COPY_AND_ASSIGN(BootControlAndroid);
 };