Support IsDeltaPayload per <package>.

Mixed full and delta payloads are now supported for multi-payload.

Bug: 36252799
Test: update_engine_unittests
Change-Id: Ic519f8399579c714a65ba9f9f948a389fcc249ed
(cherry picked from commit 4928112f8635f7a5b583171640aee2bda690ba34)
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 295d620..0026ad5 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -804,6 +804,11 @@
                         ":",
                         base::TRIM_WHITESPACE,
                         base::SPLIT_WANT_ALL);
+  vector<string> is_delta_payloads =
+      base::SplitString(app->action_postinstall_attrs[kTagIsDeltaPayload],
+                        ":",
+                        base::TRIM_WHITESPACE,
+                        base::SPLIT_WANT_ALL);
   for (size_t i = 0; i < app->packages.size(); i++) {
     const auto& package = app->packages[i];
     if (package.name.empty()) {
@@ -848,6 +853,11 @@
       return false;
     }
     LOG(INFO) << "Payload hash = " << out_package.hash;
+
+    if (i < is_delta_payloads.size())
+      out_package.is_delta = ParseBool(is_delta_payloads[i]);
+    LOG(INFO) << "Payload is delta = " << utils::ToString(out_package.is_delta);
+
     output_object->packages.push_back(std::move(out_package));
   }
 
@@ -994,8 +1004,6 @@
   if (!base::StringToUint(max, &output_object->max_failure_count_per_url))
     output_object->max_failure_count_per_url = kDefaultMaxFailureCountPerUrl;
 
-  output_object->is_delta_payload = ParseBool(attrs[kTagIsDeltaPayload]);
-
   output_object->disable_payload_backoff =
       ParseBool(attrs[kTagDisablePayloadBackoff]);
 
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 6d56603..bf2f1a0 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -127,7 +127,9 @@
            "\" MoreInfo=\"" + more_info_url + "\" Prompt=\"" + prompt +
            "\" "
            "IsDelta=\"true\" "
-           "IsDeltaPayload=\"true\" "
+           "IsDeltaPayload=\"true" +
+           (multi_package ? ":false" : "") +
+           "\" "
            "MaxDaysToScatter=\"" +
            max_days_to_scatter +
            "\" "
@@ -146,7 +148,7 @@
                       "<package name=\"package3\" size=\"333\" "
                       "hash_sha256=\"hash3\"/></packages>"
                       "<actions><action event=\"postinstall\" "
-                      "MetadataSize=\"33\"/></actions>"
+                      "MetadataSize=\"33\" IsDeltaPayload=\"false\"/></actions>"
                       "</manifest></updatecheck></app>"
                 : "") +
            (multi_app_no_update
@@ -513,6 +515,7 @@
   EXPECT_EQ(fake_update_response_.more_info_url, response.more_info_url);
   EXPECT_EQ(fake_update_response_.hash, response.packages[0].hash);
   EXPECT_EQ(fake_update_response_.size, response.packages[0].size);
+  EXPECT_EQ(true, response.packages[0].is_delta);
   EXPECT_EQ(fake_update_response_.prompt == "true", response.prompt);
   EXPECT_EQ(fake_update_response_.deadline, response.deadline);
   // Omaha cohort attribets are not set in the response, so they should not be
@@ -543,11 +546,13 @@
             response.packages[1].payload_urls[0]);
   EXPECT_EQ(fake_update_response_.hash, response.packages[0].hash);
   EXPECT_EQ(fake_update_response_.size, response.packages[0].size);
+  EXPECT_EQ(true, response.packages[0].is_delta);
   EXPECT_EQ(11u, response.packages[0].metadata_size);
   ASSERT_EQ(2u, response.packages.size());
   EXPECT_EQ(string("hash2"), response.packages[1].hash);
   EXPECT_EQ(222u, response.packages[1].size);
   EXPECT_EQ(22u, response.packages[1].metadata_size);
+  EXPECT_EQ(false, response.packages[1].is_delta);
 }
 
 TEST_F(OmahaRequestActionTest, MultiAppUpdateTest) {
@@ -572,10 +577,12 @@
   EXPECT_EQ(fake_update_response_.hash, response.packages[0].hash);
   EXPECT_EQ(fake_update_response_.size, response.packages[0].size);
   EXPECT_EQ(11u, response.packages[0].metadata_size);
+  EXPECT_EQ(true, response.packages[0].is_delta);
   ASSERT_EQ(2u, response.packages.size());
   EXPECT_EQ(string("hash3"), response.packages[1].hash);
   EXPECT_EQ(333u, response.packages[1].size);
   EXPECT_EQ(33u, response.packages[1].metadata_size);
+  EXPECT_EQ(false, response.packages[1].is_delta);
 }
 
 TEST_F(OmahaRequestActionTest, MultiAppPartialUpdateTest) {
@@ -626,13 +633,16 @@
   EXPECT_EQ(fake_update_response_.hash, response.packages[0].hash);
   EXPECT_EQ(fake_update_response_.size, response.packages[0].size);
   EXPECT_EQ(11u, response.packages[0].metadata_size);
+  EXPECT_EQ(true, response.packages[0].is_delta);
   ASSERT_EQ(3u, response.packages.size());
   EXPECT_EQ(string("hash2"), response.packages[1].hash);
   EXPECT_EQ(222u, response.packages[1].size);
   EXPECT_EQ(22u, response.packages[1].metadata_size);
+  EXPECT_EQ(false, response.packages[1].is_delta);
   EXPECT_EQ(string("hash3"), response.packages[2].hash);
   EXPECT_EQ(333u, response.packages[2].size);
   EXPECT_EQ(33u, response.packages[2].metadata_size);
+  EXPECT_EQ(false, response.packages[2].is_delta);
 }
 
 TEST_F(OmahaRequestActionTest, ExtraHeadersSentTest) {
diff --git a/omaha_response.h b/omaha_response.h
index 395891f..c702068 100644
--- a/omaha_response.h
+++ b/omaha_response.h
@@ -46,6 +46,9 @@
     uint64_t metadata_size = 0;
     std::string metadata_signature;
     std::string hash;
+    // True if the payload described in this response is a delta payload.
+    // False if it's a full payload.
+    bool is_delta = false;
   };
   std::vector<Package> packages;
 
@@ -58,10 +61,6 @@
   uint32_t max_failure_count_per_url = 0;
   bool prompt = false;
 
-  // True if the payload described in this response is a delta payload.
-  // False if it's a full payload.
-  bool is_delta_payload = false;
-
   // True if the Omaha rule instructs us to disable the back-off logic
   // on the client altogether. False otherwise.
   bool disable_payload_backoff = false;
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index f4d962e..189fe6b 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -99,7 +99,9 @@
         {.size = package.size,
          .metadata_size = package.metadata_size,
          .metadata_signature = package.metadata_signature,
-         .hash = raw_hash});
+         .hash = raw_hash,
+         .type = package.is_delta ? InstallPayloadType::kDelta
+                                  : InstallPayloadType::kFull});
     update_check_response_hash += package.hash + ":";
   }
   install_plan_.public_key_rsa = response.public_key_rsa;
@@ -118,9 +120,6 @@
                                               update_check_response_hash))
         << "Unable to save the update check response hash.";
   }
-  install_plan_.payload_type = response.is_delta_payload
-                                   ? InstallPayloadType::kDelta
-                                   : InstallPayloadType::kFull;
 
   install_plan_.source_slot = system_state_->boot_control()->GetCurrentSlot();
   install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index ab5e275..94c5c60 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -340,7 +340,7 @@
   const InstallPlan::Partition& install_part =
       install_plan_->partitions[num_previous_partitions + current_partition_];
   // Open source fds if we have a delta payload with minor version >= 2.
-  if (install_plan_->payload_type == InstallPayloadType::kDelta &&
+  if (payload_->type == InstallPayloadType::kDelta &&
       GetMinorVersion() != kInPlaceMinorPayloadVersion) {
     source_path_ = install_part.source_path;
     int err;
@@ -431,7 +431,7 @@
   if (manifest_.has_minor_version()) {
     return manifest_.minor_version();
   } else {
-    return install_plan_->payload_type == InstallPayloadType::kDelta
+    return payload_->type == InstallPayloadType::kDelta
                ? kSupportedMinorPayloadVersion
                : kFullPayloadMinorVersion;
   }
@@ -1427,14 +1427,14 @@
   InstallPayloadType actual_payload_type =
       has_old_fields ? InstallPayloadType::kDelta : InstallPayloadType::kFull;
 
-  if (install_plan_->payload_type == InstallPayloadType::kUnknown) {
+  if (payload_->type == InstallPayloadType::kUnknown) {
     LOG(INFO) << "Detected a '"
               << InstallPayloadTypeToString(actual_payload_type)
               << "' payload.";
-    install_plan_->payload_type = actual_payload_type;
-  } else if (install_plan_->payload_type != actual_payload_type) {
+    payload_->type = actual_payload_type;
+  } else if (payload_->type != actual_payload_type) {
     LOG(ERROR) << "InstallPlan expected a '"
-               << InstallPayloadTypeToString(install_plan_->payload_type)
+               << InstallPayloadTypeToString(payload_->type)
                << "' payload but the downloaded manifest contains a '"
                << InstallPayloadTypeToString(actual_payload_type)
                << "' payload.";
diff --git a/payload_consumer/delta_performer_integration_test.cc b/payload_consumer/delta_performer_integration_test.cc
index a3f653b..bc67d93 100644
--- a/payload_consumer/delta_performer_integration_test.cc
+++ b/payload_consumer/delta_performer_integration_test.cc
@@ -719,12 +719,11 @@
 
   // Update the A image in place.
   InstallPlan* install_plan = &state->install_plan;
-  install_plan->payloads.resize(1);
   install_plan->hash_checks_mandatory = hash_checks_mandatory;
-  install_plan->payloads[0].metadata_size = state->metadata_size;
-  install_plan->payload_type = (full_kernel && full_rootfs)
-                                   ? InstallPayloadType::kFull
-                                   : InstallPayloadType::kDelta;
+  install_plan->payloads = {{.metadata_size = state->metadata_size,
+                             .type = (full_kernel && full_rootfs)
+                                         ? InstallPayloadType::kFull
+                                         : InstallPayloadType::kDelta}};
   install_plan->source_slot = 0;
   install_plan->target_slot = 1;
 
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index 3af13ec..1e06e1a 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -103,7 +103,7 @@
                              uint64_t major_version,
                              InstallPayloadType payload_type,
                              ErrorCode expected) {
-    install_plan_.payload_type = payload_type;
+    payload_.type = payload_type;
 
     // The Manifest we are validating.
     performer_.manifest_.CopyFrom(manifest);
@@ -338,7 +338,7 @@
 };
 
 TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
-  install_plan_.payload_type = InstallPayloadType::kFull;
+  payload_.type = InstallPayloadType::kFull;
   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
                                             std::end(kRandomString));
   expected_data.resize(4096);  // block size
@@ -357,7 +357,7 @@
 }
 
 TEST_F(DeltaPerformerTest, ShouldCancelTest) {
-  install_plan_.payload_type = InstallPayloadType::kFull;
+  payload_.type = InstallPayloadType::kFull;
   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
                                             std::end(kRandomString));
   expected_data.resize(4096);  // block size
diff --git a/payload_consumer/download_action_unittest.cc b/payload_consumer/download_action_unittest.cc
index 9d85550..7d3ac6c 100644
--- a/payload_consumer/download_action_unittest.cc
+++ b/payload_consumer/download_action_unittest.cc
@@ -141,8 +141,8 @@
 
   uint64_t size = data.size() - 1;
   InstallPlan install_plan;
-  install_plan.payload_type = InstallPayloadType::kDelta;
-  install_plan.payloads.push_back({.size = size});
+  install_plan.payloads.push_back(
+      {.size = size, .type = InstallPayloadType::kDelta});
   // We pull off the first byte from data and seek past it.
   EXPECT_TRUE(HashCalculator::RawHashOfBytes(
       &data[1], data.size() - 1, &install_plan.payloads[0].hash));
diff --git a/payload_consumer/filesystem_verifier_action.cc b/payload_consumer/filesystem_verifier_action.cc
index 4f30582..5edde9e 100644
--- a/payload_consumer/filesystem_verifier_action.cc
+++ b/payload_consumer/filesystem_verifier_action.cc
@@ -204,8 +204,10 @@
       if (partition.target_hash != hasher_->raw_hash()) {
         LOG(ERROR) << "New '" << partition.name
                    << "' partition verification failed.";
-        if (install_plan_.payload_type == InstallPayloadType::kFull)
+        if (partition.source_hash.empty()) {
+          // No need to verify source if it is a full payload.
           return Cleanup(ErrorCode::kNewRootfsVerificationError);
+        }
         // If we have not verified source partition yet, now that the target
         // partition does not match, and it's not a full payload, we need to
         // switch to kVerifySourceHash step to check if it's because the source
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 5f004bf..d5d745b 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -42,7 +42,6 @@
 
 bool InstallPlan::operator==(const InstallPlan& that) const {
   return ((is_resume == that.is_resume) &&
-          (payload_type == that.payload_type) &&
           (download_url == that.download_url) && (payloads == that.payloads) &&
           (source_slot == that.source_slot) &&
           (target_slot == that.target_slot) && (partitions == that.partitions));
@@ -67,15 +66,15 @@
   for (const auto& payload : payloads) {
     payloads_str += base::StringPrintf(
         ", payload: (size: %" PRIu64 ", metadata_size: %" PRIu64
-        ", metadata signature: %s, hash: %s)",
+        ", metadata signature: %s, hash: %s, payload type: %s)",
         payload.size,
         payload.metadata_size,
         payload.metadata_signature.c_str(),
-        base::HexEncode(payload.hash.data(), payload.hash.size()).c_str());
+        base::HexEncode(payload.hash.data(), payload.hash.size()).c_str(),
+        InstallPayloadTypeToString(payload.type).c_str());
   }
 
   LOG(INFO) << "InstallPlan: " << (is_resume ? "resume" : "new_update")
-            << ", payload type: " << InstallPayloadTypeToString(payload_type)
             << ", source_slot: " << BootControlInterface::SlotName(source_slot)
             << ", target_slot: " << BootControlInterface::SlotName(target_slot)
             << ", url: " << download_url << payloads_str << partitions_str
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index d8d9f57..6dd5a73 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -52,7 +52,6 @@
   bool LoadPartitionsFromSlots(BootControlInterface* boot_control);
 
   bool is_resume{false};
-  InstallPayloadType payload_type{InstallPayloadType::kUnknown};
   std::string download_url;  // url to download from
   std::string version;       // version we are installing.
 
@@ -61,6 +60,7 @@
     uint64_t metadata_size = 0;      // size of the metadata
     std::string metadata_signature;  // signature of the metadata in base64
     brillo::Blob hash;               // SHA256 hash of the payload
+    InstallPayloadType type{InstallPayloadType::kUnknown};
     // Only download manifest and fill in partitions in install plan without
     // apply the payload if true. Will be set by DownloadAction when resuming
     // multi-payload.
@@ -69,7 +69,8 @@
     bool operator==(const Payload& that) const {
       return size == that.size && metadata_size == that.metadata_size &&
              metadata_signature == that.metadata_signature &&
-             hash == that.hash && already_applied == that.already_applied;
+             hash == that.hash && type == that.type &&
+             already_applied == that.already_applied;
     }
   };
   std::vector<Payload> payloads;
diff --git a/payload_state.cc b/payload_state.cc
index 2a7030f..987cf1c 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -386,14 +386,16 @@
     LOG(INFO) << "Payload backoff disabled for interactive update checks.";
     return false;
   }
-  if (response_.is_delta_payload) {
-    // If delta payloads fail, we want to fallback quickly to full payloads as
-    // they are more likely to succeed. Exponential backoffs would greatly
-    // slow down the fallback to full payloads.  So we don't backoff for delta
-    // payloads.
-    LOG(INFO) << "No backoffs for delta payloads. "
-              << "Can proceed with the download";
-    return false;
+  for (const auto& package : response_.packages) {
+    if (package.is_delta) {
+      // If delta payloads fail, we want to fallback quickly to full payloads as
+      // they are more likely to succeed. Exponential backoffs would greatly
+      // slow down the fallback to full payloads.  So we don't backoff for delta
+      // payloads.
+      LOG(INFO) << "No backoffs for delta payloads. "
+                << "Can proceed with the download";
+      return false;
+    }
   }
 
   if (!system_state_->hardware()->IsOfficialBuild()) {
@@ -434,7 +436,7 @@
 
 void PayloadState::IncrementFullPayloadAttemptNumber() {
   // Update the payload attempt number for full payloads and the backoff time.
-  if (response_.is_delta_payload) {
+  if (response_.packages[payload_index_].is_delta) {
     LOG(INFO) << "Not incrementing payload attempt number for delta payloads";
     return;
   }
@@ -553,16 +555,17 @@
 }
 
 PayloadType PayloadState::CalculatePayloadType() {
-  PayloadType payload_type;
-  OmahaRequestParams* params = system_state_->request_params();
-  if (response_.is_delta_payload) {
-    payload_type = kPayloadTypeDelta;
-  } else if (params->delta_okay()) {
-    payload_type = kPayloadTypeFull;
-  } else {  // Full payload, delta was not allowed by request.
-    payload_type = kPayloadTypeForcedFull;
+  for (const auto& package : response_.packages) {
+    if (package.is_delta) {
+      return kPayloadTypeDelta;
+    }
   }
-  return payload_type;
+  OmahaRequestParams* params = system_state_->request_params();
+  if (params->delta_okay()) {
+    return kPayloadTypeFull;
+  }
+  // Full payload, delta was not allowed by request.
+  return kPayloadTypeForcedFull;
 }
 
 // TODO(zeuthen): Currently we don't report the UpdateEngine.Attempt.*
@@ -817,12 +820,14 @@
         "  Sha256 Hash = %s\n"
         "  Metadata Size = %ju\n"
         "  Metadata Signature = %s\n"
+        "  Is Delta = %d\n"
         "  NumURLs = %zu\n",
         i,
         static_cast<uintmax_t>(package.size),
         package.hash.c_str(),
         static_cast<uintmax_t>(package.metadata_size),
         package.metadata_signature.c_str(),
+        package.is_delta,
         candidate_urls_[i].size());
 
     for (size_t j = 0; j < candidate_urls_[i].size(); j++)
@@ -831,10 +836,8 @@
   }
 
   response_sign += base::StringPrintf(
-      "Is Delta Payload = %d\n"
       "Max Failure Count Per Url = %d\n"
       "Disable Payload Backoff = %d\n",
-      response_.is_delta_payload,
       response_.max_failure_count_per_url,
       response_.disable_payload_backoff);
   return response_sign;
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index 6366a7e..4546180 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -61,6 +61,7 @@
 
 static void SetupPayloadStateWith2Urls(string hash,
                                        bool http_enabled,
+                                       bool is_delta_payload,
                                        PayloadState* payload_state,
                                        OmahaResponse* response) {
   response->packages.clear();
@@ -68,7 +69,8 @@
                                 .size = 523456789,
                                 .metadata_size = 558123,
                                 .metadata_signature = "metasign",
-                                .hash = hash});
+                                .hash = hash,
+                                .is_delta = is_delta_payload});
   response->max_failure_count_per_url = 3;
   payload_state->SetResponse(*response);
   string stored_response_sign = payload_state->GetResponseSignature();
@@ -88,13 +90,13 @@
       "  Sha256 Hash = %s\n"
       "  Metadata Size = 558123\n"
       "  Metadata Signature = metasign\n"
+      "  Is Delta = %d\n"
       "%s"
-      "Is Delta Payload = %d\n"
       "Max Failure Count Per Url = %d\n"
       "Disable Payload Backoff = %d\n",
       hash.c_str(),
+      response->packages[0].is_delta,
       (http_enabled ? expected_urls_both : expected_url_https_only).c_str(),
-      response->is_delta_payload,
       response->max_failure_count_per_url,
       response->disable_payload_backoff);
   EXPECT_EQ(expected_response_sign, stored_response_sign);
@@ -131,7 +133,6 @@
   payload_state.SetResponse(response);
   string stored_response_sign = payload_state.GetResponseSignature();
   string expected_response_sign =
-      "Is Delta Payload = 0\n"
       "Max Failure Count Per Url = 0\n"
       "Disable Payload Backoff = 0\n";
   EXPECT_EQ(expected_response_sign, stored_response_sign);
@@ -183,9 +184,9 @@
       "  Sha256 Hash = hash\n"
       "  Metadata Size = 58123\n"
       "  Metadata Signature = msign\n"
+      "  Is Delta = 0\n"
       "  NumURLs = 1\n"
       "  Candidate Url0 = https://single.url.test\n"
-      "Is Delta Payload = 0\n"
       "Max Failure Count Per Url = 0\n"
       "Disable Payload Backoff = 0\n";
   EXPECT_EQ(expected_response_sign, stored_response_sign);
@@ -235,10 +236,10 @@
       "  Sha256 Hash = rhash\n"
       "  Metadata Size = 558123\n"
       "  Metadata Signature = metasign\n"
+      "  Is Delta = 0\n"
       "  NumURLs = 2\n"
       "  Candidate Url0 = http://multiple.url.test\n"
       "  Candidate Url1 = https://multiple.url.test\n"
-      "Is Delta Payload = 0\n"
       "Max Failure Count Per Url = 0\n"
       "Disable Payload Backoff = 0\n";
   EXPECT_EQ(expected_response_sign, stored_response_sign);
@@ -282,7 +283,8 @@
 
   // This does a SetResponse which causes all the states to be set to 0 for
   // the first time.
-  SetupPayloadStateWith2Urls("Hash1235", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash1235", true, false, &payload_state, &response);
   EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
 
   // Verify that on the first error, the URL index advances to 1.
@@ -315,7 +317,8 @@
     .Times(AnyNumber());
 
   // Set the first response.
-  SetupPayloadStateWith2Urls("Hash5823", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash5823", true, false, &payload_state, &response);
   EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // Advance the URL index to 1 by faking an error.
@@ -325,7 +328,8 @@
   EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
 
   // Now, slightly change the response and set it again.
-  SetupPayloadStateWith2Urls("Hash8225", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8225", true, false, &payload_state, &response);
   EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // Fake an error again.
@@ -334,7 +338,8 @@
   EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
 
   // Return a third different response.
-  SetupPayloadStateWith2Urls("Hash9999", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash9999", true, false, &payload_state, &response);
   EXPECT_EQ(3, payload_state.GetNumResponsesSeen());
 
   // Make sure the url index was reset to 0 because of the new response.
@@ -405,7 +410,8 @@
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
 
-  SetupPayloadStateWith2Urls("Hash5873", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash5873", true, false, &payload_state, &response);
   EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // This should advance the URL index.
@@ -484,7 +490,8 @@
   EXPECT_TRUE(payload_state.ShouldBackoffDownload());
 
   // Now, slightly change the response and set it again.
-  SetupPayloadStateWith2Urls("Hash8532", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8532", true, false, &payload_state, &response);
   EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // Make sure the url index was reset to 0 because of the new response.
@@ -498,7 +505,6 @@
 
 TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulFullDownload) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
   NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
@@ -524,7 +530,8 @@
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
 
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   // This should just advance the payload attempt number;
   EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
@@ -539,7 +546,6 @@
 
 TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulDeltaDownload) {
   OmahaResponse response;
-  response.is_delta_payload = true;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
   NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
@@ -564,7 +570,7 @@
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
 
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls("Hash8593", true, true, &payload_state, &response);
 
   // This should just advance the payload attempt number;
   EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
@@ -583,7 +589,8 @@
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash4427", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash4427", true, false, &payload_state, &response);
 
   // Generate enough events to advance URL index, failure count and
   // payload attempt number all to 1.
@@ -619,7 +626,8 @@
   // response was different. We want to specifically test that even if the
   // response is same, we should reset the state if we find it corrupted.
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state2));
-  SetupPayloadStateWith2Urls("Hash4427", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash4427", true, false, &payload_state, &response);
 
   // Make sure all counters get reset to 0 because of the corrupted URL index
   // we supplied above.
@@ -632,7 +640,6 @@
 
 TEST(PayloadStateTest, NoBackoffInteractiveChecks) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
   OmahaRequestParams params(&fake_system_state);
@@ -640,7 +647,8 @@
   fake_system_state.set_request_params(&params);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash6437", true, false, &payload_state, &response);
 
   // Simulate two failures (enough to cause payload backoff) and check
   // again that we're ready to re-download without any backoff as this is
@@ -655,7 +663,6 @@
 
 TEST(PayloadStateTest, NoBackoffForP2PUpdates) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
   OmahaRequestParams params(&fake_system_state);
@@ -663,7 +670,8 @@
   fake_system_state.set_request_params(&params);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash6437", true, false, &payload_state, &response);
 
   // Simulate two failures (enough to cause payload backoff) and check
   // again that we're ready to re-download without any backoff as this is
@@ -686,12 +694,11 @@
 
 TEST(PayloadStateTest, NoBackoffForDeltaPayloads) {
   OmahaResponse response;
-  response.is_delta_payload = true;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls("Hash6437", true, true, &payload_state, &response);
 
   // Simulate a successful download and see that we're ready to download
   // again without any backoff as this is a delta payload.
@@ -731,12 +738,12 @@
 
 TEST(PayloadStateTest, BackoffPeriodsAreInCorrectRange) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8939", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8939", true, false, &payload_state, &response);
 
   CheckPayloadBackoffState(&payload_state, 1,  TimeDelta::FromDays(1));
   CheckPayloadBackoffState(&payload_state, 2,  TimeDelta::FromDays(2));
@@ -757,7 +764,8 @@
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8939", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8939", true, false, &payload_state, &response);
 
   // Simulate a successful download and see that we are ready to download
   // again without any backoff.
@@ -785,7 +793,8 @@
   uint64_t http_total = 0;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash3286", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash3286", true, false, &payload_state, &response);
   EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // Simulate a previous attempt with in order to set an initial non-zero value
@@ -802,7 +811,8 @@
 
   // Change the response hash so as to simulate a new response which will
   // reset the current bytes downloaded, but not the total bytes downloaded.
-  SetupPayloadStateWith2Urls("Hash9904", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash9904", true, false, &payload_state, &response);
   EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // First, simulate successful download of a few bytes over HTTP.
@@ -904,7 +914,8 @@
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash3286", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash3286", true, false, &payload_state, &response);
 
   // Simulate progress in order to mark HTTP as one of the sources used.
   uint64_t num_bytes = 42 * 1000 * 1000;
@@ -935,7 +946,8 @@
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
 
   // Set the first response.
-  SetupPayloadStateWith2Urls("Hash5823", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash5823", true, false, &payload_state, &response);
 
   uint64_t num_bytes = 10000;
   payload_state.DownloadProgress(num_bytes);
@@ -1052,7 +1064,8 @@
   // Check that durations are correct for a successful update where
   // time has advanced 7 seconds on the wall clock and 4 seconds on
   // the monotonic clock.
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
   fake_clock.SetWallclockTime(Time::FromInternalValue(8000000));
   fake_clock.SetMonotonicTime(Time::FromInternalValue(6000000));
   payload_state.UpdateSucceeded();
@@ -1060,7 +1073,8 @@
   EXPECT_EQ(payload_state.GetUpdateDurationUptime().InMicroseconds(), 4000000);
 
   // Check that durations are reset when a new response comes in.
-  SetupPayloadStateWith2Urls("Hash8594", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8594", true, false, &payload_state, &response);
   EXPECT_EQ(payload_state.GetUpdateDuration().InMicroseconds(), 0);
   EXPECT_EQ(payload_state.GetUpdateDurationUptime().InMicroseconds(), 0);
 
@@ -1109,7 +1123,8 @@
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
 
   // Make the update succeed.
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
   payload_state.UpdateSucceeded();
 
   // Check that the marker was written.
@@ -1251,7 +1266,8 @@
       .WillRepeatedly(Return(false));
 
   // Set the first response.
-  SetupPayloadStateWith2Urls("Hash8433", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8433", true, false, &payload_state, &response);
 
   // Check that we use the HTTP URL since there is no value set for allowing
   // http.
@@ -1262,7 +1278,8 @@
       .WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(true)));
 
   // Reset state and set again.
-  SetupPayloadStateWith2Urls("Hash8433", false, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8433", false, false, &payload_state, &response);
 
   // Check that we skip the HTTP URL and use only the HTTPS url.
   EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
@@ -1276,7 +1293,8 @@
   EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
 
   // Now, slightly change the response and set it again.
-  SetupPayloadStateWith2Urls("Hash2399", false, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash2399", false, false, &payload_state, &response);
 
   // Check that we still skip the HTTP URL and use only the HTTPS url.
   EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
@@ -1292,7 +1310,8 @@
   // so that we can test that the state is reset not because of the
   // hash but because of the policy change which results in candidate url
   // list change.
-  SetupPayloadStateWith2Urls("Hash2399", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash2399", true, false, &payload_state, &response);
 
   // Check that we use the HTTP URL now and the failure count is reset.
   EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
@@ -1308,12 +1327,11 @@
 
 TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsDelta) {
   OmahaResponse response;
-  response.is_delta_payload = true;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls("Hash6437", true, true, &payload_state, &response);
 
   // Simulate a successful download and update.
   payload_state.DownloadComplete();
@@ -1334,7 +1352,7 @@
   fake_system_state.set_request_params(&params);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls("Hash6437", true, true, &payload_state, &response);
 
   payload_state.DownloadComplete();
 
@@ -1349,12 +1367,12 @@
 
 TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsForcedFull) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash6437", true, false, &payload_state, &response);
 
   // Mock the request to a request where the delta was disabled.
   OmahaRequestParams params(&fake_system_state);
@@ -1377,12 +1395,12 @@
 
 TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsFull) {
   OmahaResponse response;
-  response.is_delta_payload = false;
   PayloadState payload_state;
   FakeSystemState fake_system_state;
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash6437", true, false, &payload_state, &response);
 
   // Mock the request to a request where the delta is enabled, although the
   // result is full.
@@ -1412,7 +1430,8 @@
   fake_system_state.set_prefs(&fake_prefs);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash3141", true, false, &payload_state, &response);
 
   // Simulate a successful download and update.
   payload_state.DownloadComplete();
@@ -1454,7 +1473,8 @@
   fake_boot_control->SetCurrentSlot(0);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash3141", true, false, &payload_state, &response);
 
   // Simulate a successful download and update.
   payload_state.DownloadComplete();
@@ -1483,7 +1503,8 @@
 
   fake_system_state.set_prefs(&fake_prefs);
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash3141", true, false, &payload_state, &response);
 
   // Simulate a successful download and update.
   payload_state.DownloadComplete();
@@ -1525,7 +1546,8 @@
   fake_system_state.set_prefs(&fake_prefs);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   // Should allow exactly kMaxP2PAttempts...
   for (int n = 0; n < kMaxP2PAttempts; n++) {
@@ -1547,7 +1569,8 @@
   fake_system_state.set_clock(&fake_clock);
   fake_system_state.set_prefs(&fake_prefs);
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   // Set the clock to 1 second.
   Time epoch = Time::FromInternalValue(1000000);
@@ -1590,7 +1613,8 @@
 
   fake_system_state.set_prefs(&fake_prefs);
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   Time null_time = Time();
   EXPECT_EQ(null_time, payload_state.GetP2PFirstAttemptTimestamp());
@@ -1606,7 +1630,8 @@
   fake_system_state.set_clock(&fake_clock);
   fake_system_state.set_prefs(&fake_prefs);
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   // Set the clock to something known.
   Time time = Time::FromInternalValue(12345);
@@ -1635,7 +1660,8 @@
   fake_system_state.set_prefs(&fake_prefs);
 
   EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
-  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash8593", true, false, &payload_state, &response);
 
   // Set the clock to something known.
   Time time = Time::FromInternalValue(12345);
@@ -1647,7 +1673,8 @@
   EXPECT_EQ(time, payload_state.GetP2PFirstAttemptTimestamp());
 
   // Set a new response...
-  SetupPayloadStateWith2Urls("Hash9904", true, &payload_state, &response);
+  SetupPayloadStateWith2Urls(
+      "Hash9904", true, false, &payload_state, &response);
 
   // ... and check that it clears the P2P state vars.
   Time null_time = Time();
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 09549f8..286ed65 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -161,6 +161,8 @@
                             &payload.metadata_size)) {
     payload.metadata_size = 0;
   }
+  // The |payload.type| is not used anymore since minor_version 3.
+  payload.type = InstallPayloadType::kUnknown;
   install_plan_.payloads.push_back(payload);
 
   // The |public_key_rsa| key would override the public key stored on disk.
@@ -177,9 +179,6 @@
       LOG(WARNING) << "Unable to save the update check response hash.";
     }
   }
-  // The |payload_type| is not used anymore since minor_version 3.
-  install_plan_.payload_type = InstallPayloadType::kUnknown;
-
   install_plan_.source_slot = boot_control_->GetCurrentSlot();
   install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;