Merge qt-r1-dev-plus-aosp-without-vendor (5817612) into stage-aosp-master

No content change.

Bug: 135460123
Change-Id: I6e5faa426cf7865985bc8e34b0bf2f45525bd799
Merged-In: I0f2a4d898ccfab7f5215d9bbb3c2c9fd4f7329cf
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index 6f02a07..3b92191 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -62,6 +62,8 @@
 
     ON_CALL(dynamicControl(), GetDynamicPartitionsFeatureFlag())
         .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::LAUNCH)));
+    ON_CALL(dynamicControl(), GetVirtualAbFeatureFlag())
+        .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::NONE)));
     ON_CALL(dynamicControl(), DeviceExists(_)).WillByDefault(Return(true));
     ON_CALL(dynamicControl(), GetDeviceDir(_))
         .WillByDefault(Invoke([](auto path) {
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index 5a2ccb1..b973232 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -53,6 +53,8 @@
 constexpr char kUseDynamicPartitions[] = "ro.boot.dynamic_partitions";
 constexpr char kRetrfoitDynamicPartitions[] =
     "ro.boot.dynamic_partitions_retrofit";
+constexpr char kVirtualAbEnabled[] = "ro.virtual_ab.enabled";
+constexpr char kVirtualAbRetrofit[] = "ro.virtual_ab.retrofit";
 constexpr uint64_t kMapTimeoutMillis = 1000;
 
 DynamicPartitionControlAndroid::~DynamicPartitionControlAndroid() {
@@ -81,6 +83,10 @@
   return GetFeatureFlag(kUseDynamicPartitions, kRetrfoitDynamicPartitions);
 }
 
+FeatureFlag DynamicPartitionControlAndroid::GetVirtualAbFeatureFlag() {
+  return GetFeatureFlag(kVirtualAbEnabled, kVirtualAbRetrofit);
+}
+
 bool DynamicPartitionControlAndroid::MapPartitionInternal(
     const std::string& super_device,
     const std::string& target_partition_name,
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index 062a2d1..d743e6e 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -30,6 +30,7 @@
   DynamicPartitionControlAndroid() = default;
   ~DynamicPartitionControlAndroid();
   FeatureFlag GetDynamicPartitionsFeatureFlag() override;
+  FeatureFlag GetVirtualAbFeatureFlag() override;
   bool MapPartitionOnDeviceMapper(const std::string& super_device,
                                   const std::string& target_partition_name,
                                   uint32_t slot,
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 5b3dfe3..1a3f664 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -44,6 +44,8 @@
 
     ON_CALL(dynamicControl(), GetDynamicPartitionsFeatureFlag())
         .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::LAUNCH)));
+    ON_CALL(dynamicControl(), GetVirtualAbFeatureFlag())
+        .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::NONE)));
 
     ON_CALL(dynamicControl(), GetDeviceDir(_))
         .WillByDefault(Invoke([](auto path) {
diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h
index b3ce4ea..9c7b8d0 100644
--- a/dynamic_partition_control_interface.h
+++ b/dynamic_partition_control_interface.h
@@ -50,6 +50,9 @@
   //        NONE iff dynamic partitions is disabled on this device.
   virtual FeatureFlag GetDynamicPartitionsFeatureFlag() = 0;
 
+  // Return the feature flags of Virtual A/B on this device.
+  virtual FeatureFlag GetVirtualAbFeatureFlag() = 0;
+
   // Map logical partition on device-mapper.
   // |super_device| is the device path of the physical partition ("super").
   // |target_partition_name| is the identifier used in metadata; for example,
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index 26fc246..aab3c4d 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -49,6 +49,7 @@
                     uint32_t,
                     const BootControlInterface::PartitionMetadata&));
   MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
+  MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
 };
 
 class MockDynamicPartitionControlAndroid
@@ -75,6 +76,7 @@
   MOCK_METHOD1(GetDeviceDir, bool(std::string*));
   MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
   MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
+  MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
 };
 
 }  // namespace chromeos_update_engine
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index 3cb891f..7c304ce 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -421,6 +421,9 @@
                 "",
                 "An info file specifying dynamic partition metadata. "
                 "Only allowed in major version 2 or newer.");
+  DEFINE_bool(disable_fec_computation,
+              false,
+              "Disables the fec data computation on device.");
 
   brillo::FlagHelper::Init(
       argc,
@@ -527,6 +530,8 @@
         << "Partition name can't be empty, see --partition_names.";
     payload_config.target.partitions.emplace_back(partition_names[i]);
     payload_config.target.partitions.back().path = new_partitions[i];
+    payload_config.target.partitions.back().disable_fec_computation =
+        FLAGS_disable_fec_computation;
     if (i < new_mapfiles.size())
       payload_config.target.partitions.back().mapfile_path = new_mapfiles[i];
   }
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index 584ac7b..e90edde 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -116,6 +116,9 @@
 
   PostInstallConfig postinstall;
   VerityConfig verity;
+
+  // Enables the on device fec data computation by default.
+  bool disable_fec_computation = false;
 };
 
 // The ImageConfig struct describes a pair of binaries kernel and rootfs and the
diff --git a/payload_generator/payload_generation_config_android.cc b/payload_generator/payload_generation_config_android.cc
index 90c053f..d950092 100644
--- a/payload_generator/payload_generation_config_android.cc
+++ b/payload_generator/payload_generation_config_android.cc
@@ -63,11 +63,13 @@
   part->verity.hash_tree_extent = ExtentForBytes(
       hashtree.hash_block_size, hashtree.tree_offset, hashtree.tree_size);
 
-  part->verity.fec_data_extent =
-      ExtentForBytes(hashtree.data_block_size, 0, hashtree.fec_offset);
-  part->verity.fec_extent = ExtentForBytes(
-      hashtree.data_block_size, hashtree.fec_offset, hashtree.fec_size);
-  part->verity.fec_roots = hashtree.fec_num_roots;
+  if (!part->disable_fec_computation) {
+    part->verity.fec_data_extent =
+        ExtentForBytes(hashtree.data_block_size, 0, hashtree.fec_offset);
+    part->verity.fec_extent = ExtentForBytes(
+        hashtree.data_block_size, hashtree.fec_offset, hashtree.fec_size);
+    part->verity.fec_roots = hashtree.fec_num_roots;
+  }
   return true;
 }
 
@@ -205,7 +207,8 @@
               ExtentForRange(hash_start_block, tree_size / block_size);
         }
         fec_ecc_metadata ecc_data;
-        if (fh.get_ecc_metadata(ecc_data) && ecc_data.valid) {
+        if (!part.disable_fec_computation && fh.get_ecc_metadata(ecc_data) &&
+            ecc_data.valid) {
           TEST_AND_RETURN_FALSE(block_size == FEC_BLOCKSIZE);
           part.verity.fec_data_extent = ExtentForRange(0, ecc_data.blocks);
           part.verity.fec_extent =
diff --git a/payload_generator/payload_generation_config_android_unittest.cc b/payload_generator/payload_generation_config_android_unittest.cc
index 53378c2..44eaf55 100644
--- a/payload_generator/payload_generation_config_android_unittest.cc
+++ b/payload_generator/payload_generation_config_android_unittest.cc
@@ -160,6 +160,24 @@
   EXPECT_EQ(2u, verity.fec_roots);
 }
 
+TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigDisableFecTest) {
+  brillo::Blob part = GetAVBPartition();
+  test_utils::WriteFileVector(temp_file_.path(), part);
+  image_config_.partitions[0].disable_fec_computation = true;
+  EXPECT_TRUE(image_config_.LoadImageSize());
+  EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
+  EXPECT_TRUE(image_config_.LoadVerityConfig());
+  const VerityConfig& verity = image_config_.partitions[0].verity;
+  EXPECT_FALSE(verity.IsEmpty());
+  EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent);
+  EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent);
+  EXPECT_EQ("sha1", verity.hash_tree_algorithm);
+  brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt));
+  EXPECT_EQ(salt, verity.hash_tree_salt);
+  EXPECT_EQ(0u, verity.fec_data_extent.num_blocks());
+  EXPECT_EQ(0u, verity.fec_extent.num_blocks());
+}
+
 TEST_F(PayloadGenerationConfigAndroidTest,
        LoadVerityConfigInvalidHashTreeTest) {
   brillo::Blob part = GetAVBPartition();
diff --git a/scripts/brillo_update_payload b/scripts/brillo_update_payload
index a238ddf..23d2d7e 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -28,12 +28,16 @@
 #  check       verify a payload using paycheck (static testing)
 #
 #  Generate command arguments:
-#  --payload             generated unsigned payload output file
-#  --source_image        if defined, generate a delta payload from the specified
-#                        image to the target_image
-#  --target_image        the target image that should be sent to clients
-#  --metadata_size_file  if defined, generate a file containing the size of the
-#                        payload metadata in bytes to the specified file
+#  --payload                  generated unsigned payload output file
+#  --source_image             if defined, generate a delta payload from the
+#                             specified image to the target_image
+#  --target_image             the target image that should be sent to clients
+#  --metadata_size_file       if defined, generate a file containing the size
+#                             of the ayload metadata in bytes to the specified
+#                             file
+#  --disable_fec_computation  Disable the on device fec data computation for
+#                             incremental update. This feature is enabled by
+#                             default
 #
 #  Hash command arguments:
 #  --unsigned_payload    the input unsigned payload to generate the hash from
@@ -182,6 +186,9 @@
     "Optional: The maximum unix timestamp of the OS allowed to apply this \
 payload, should be set to a number higher than the build timestamp of the \
 system running on the device, 0 if not specified."
+  DEFINE_string disable_fec_computation "" \
+    "Optional: Disables the on device fec data computation for incremental \
+update. This feature is enabled by default."
 fi
 if [[ "${COMMAND}" == "hash" || "${COMMAND}" == "sign" ]]; then
   DEFINE_string unsigned_payload "" "Path to the input unsigned payload."
@@ -656,6 +663,10 @@
     if [[ -n "${FORCE_MINOR_VERSION}" ]]; then
       GENERATOR_ARGS+=( --minor_version="${FORCE_MINOR_VERSION}" )
     fi
+    if [[ -n "${FLAGS_disable_fec_computation}" ]]; then
+      GENERATOR_ARGS+=(
+        --disable_fec_computation="${FLAGS_disable_fec_computation}" )
+    fi
   fi
 
   if [[ -n "${FORCE_MAJOR_VERSION}" ]]; then
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 97c53ec..08f6c20 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -750,11 +750,15 @@
         total_bytes_downloaded;
 
     int download_overhead_percentage = 0;
-    if (current_bytes_downloaded > 0) {
+    if (total_bytes_downloaded >= payload_size) {
+      CHECK_GT(payload_size, 0);
       download_overhead_percentage =
-          (total_bytes_downloaded - current_bytes_downloaded) * 100ull /
-          current_bytes_downloaded;
+          (total_bytes_downloaded - payload_size) * 100ull / payload_size;
+    } else {
+      LOG(WARNING) << "Downloaded bytes " << total_bytes_downloaded
+                   << " is smaller than the payload size " << payload_size;
     }
+
     metrics_reporter_->ReportSuccessfulUpdateMetrics(
         static_cast<int>(attempt_number),
         0,  // update abandoned count
diff --git a/update_attempter_android_unittest.cc b/update_attempter_android_unittest.cc
index 3be0b7e..721b735 100644
--- a/update_attempter_android_unittest.cc
+++ b/update_attempter_android_unittest.cc
@@ -18,6 +18,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include <android-base/properties.h>
 #include <base/time/time.h>
@@ -57,6 +58,11 @@
     update_attempter_android_.status_ = status;
   }
 
+  void AddPayload(InstallPlan::Payload&& payload) {
+    update_attempter_android_.install_plan_.payloads.push_back(
+        std::move(payload));
+  }
+
   UpdateAttempterAndroid update_attempter_android_{
       &daemon_state_, &prefs_, &boot_control_, &hardware_};
 
@@ -143,9 +149,13 @@
       .Times(1);
   EXPECT_CALL(*metrics_reporter_,
               ReportSuccessfulUpdateMetrics(
-                  2, 0, _, _, _, _, duration, duration_uptime, 3, _))
+                  2, 0, _, 50, _, _, duration, duration_uptime, 3, _))
       .Times(1);
 
+  // Adds a payload of 50 bytes to the InstallPlan.
+  InstallPlan::Payload payload;
+  payload.size = 50;
+  AddPayload(std::move(payload));
   SetUpdateStatus(UpdateStatus::UPDATE_AVAILABLE);
   update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
 
@@ -179,15 +189,20 @@
                   _,
                   _,
                   _,
-                  _,
+                  50,
                   test_utils::DownloadSourceMatcher(total_bytes),
-                  125,
+                  80,
                   _,
                   _,
                   _,
                   _))
       .Times(1);
 
+  // Adds a payload of 50 bytes to the InstallPlan.
+  InstallPlan::Payload payload;
+  payload.size = 50;
+  AddPayload(std::move(payload));
+
   // The first update fails after receiving 50 bytes in total.
   update_attempter_android_.BytesReceived(30, 50, 200);
   update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kError);
@@ -199,7 +214,7 @@
       metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
 
   // The second update succeeds after receiving 40 bytes, which leads to a
-  // overhead of 50 / 40 = 125%.
+  // overhead of (90 - 50) / 50 = 80%.
   update_attempter_android_.BytesReceived(40, 40, 50);
   update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
   // Both prefs should be cleared.
diff --git a/update_engine.rc b/update_engine.rc
index 90ca4c6..b9f80fc 100644
--- a/update_engine.rc
+++ b/update_engine.rc
@@ -2,7 +2,7 @@
     class late_start
     user root
     group root system wakelock inet cache media_rw
-    writepid /dev/cpuset/system-background/tasks
+    writepid /dev/cpuset/system-background/tasks /dev/blkio/background/tasks
     disabled
 
 on property:ro.boot.slot_suffix=*