Merge "InstallPackage now takes a package as parameter"
diff --git a/install/adb_install.cpp b/install/adb_install.cpp
index 2de1075..37280a3 100644
--- a/install/adb_install.cpp
+++ b/install/adb_install.cpp
@@ -110,7 +110,11 @@
         break;
       }
     }
-    *result = InstallPackage(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, ui);
+
+    auto package =
+        Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME,
+                                   std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
+    *result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0, ui);
     break;
   }
 
diff --git a/install/fuse_sdcard_install.cpp b/install/fuse_sdcard_install.cpp
index a5caa6e..9fdb2f3 100644
--- a/install/fuse_sdcard_install.cpp
+++ b/install/fuse_sdcard_install.cpp
@@ -182,8 +182,11 @@
         break;
       }
     }
-
-    result = InstallPackage(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /* retry_count */, ui);
+    auto package =
+        Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME,
+                                   std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
+    result =
+        InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0 /* retry_count */, ui);
     break;
   }
 
diff --git a/install/include/install/install.h b/install/include/install/install.h
index 44a5cde..b4b3a91 100644
--- a/install/include/install/install.h
+++ b/install/include/install/install.h
@@ -44,11 +44,12 @@
   BRICK,
 };
 
-// Installs the given update package. This function should also wipe the cache partition after a
-// successful installation if |should_wipe_cache| is true or an updater command asks to wipe the
-// cache.
-InstallResult InstallPackage(const std::string& package, bool should_wipe_cache, bool needs_mount,
-                             int retry_count, RecoveryUI* ui);
+// Installs the given update package. The package_id is a string provided by the caller (e.g. the
+// package path) to identify the package and log to last_install. This function should also wipe the
+// cache partition after a successful installation if |should_wipe_cache| is true or an updater
+// command asks to wipe the cache.
+InstallResult InstallPackage(Package* package, const std::string_view package_id,
+                             bool should_wipe_cache, int retry_count, RecoveryUI* ui);
 
 // Verifies the package by ota keys. Returns true if the package is verified successfully,
 // otherwise returns false.
diff --git a/install/include/install/package.h b/install/include/install/package.h
index cd44d10..0b42332 100644
--- a/install/include/install/package.h
+++ b/install/include/install/package.h
@@ -28,6 +28,11 @@
 
 #include "verifier.h"
 
+enum class PackageType {
+  kMemory,
+  kFile,
+};
+
 // This class serves as a wrapper for an OTA update package. It aims to provide the common
 // interface for both packages loaded in memory and packages read from fd.
 class Package : public VerifierInterface {
@@ -41,6 +46,10 @@
 
   virtual ~Package() = default;
 
+  virtual PackageType GetType() const = 0;
+
+  virtual std::string GetPath() const = 0;
+
   // Opens the package as a zip file and returns the ZipArchiveHandle.
   virtual ZipArchiveHandle GetZipArchiveHandle() = 0;
 
diff --git a/install/install.cpp b/install/install.cpp
index 445f3ab..09b8839 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -320,16 +320,21 @@
 }
 
 // If the package contains an update binary, extract it and run it.
-static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandle zip,
-                                     bool* wipe_cache, std::vector<std::string>* log_buffer,
-                                     int retry_count, int* max_temperature, RecoveryUI* ui) {
+static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache,
+                                     std::vector<std::string>* log_buffer, int retry_count,
+                                     int* max_temperature, RecoveryUI* ui) {
   std::map<std::string, std::string> metadata;
+  auto zip = package->GetZipArchiveHandle();
   if (!ReadMetadataFromPackage(zip, &metadata)) {
     LOG(ERROR) << "Failed to parse metadata in the zip file";
     return INSTALL_CORRUPT;
   }
 
   bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false);
+  if (is_ab) {
+    CHECK(package->GetType() == PackageType::kFile);
+  }
+
   // Verify against the metadata in the package first.
   if (is_ab && !CheckPackageMetadata(metadata, OtaType::AB)) {
     log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
@@ -379,10 +384,12 @@
   //       updater requests logging the string (e.g. cause of the failure).
   //
 
+  std::string package_path = package->GetPath();
+
   std::vector<std::string> args;
   if (auto setup_result =
-          is_ab ? SetUpAbUpdateCommands(package, zip, pipe_write.get(), &args)
-                : SetUpNonAbUpdateCommands(package, zip, retry_count, pipe_write.get(), &args);
+          is_ab ? SetUpAbUpdateCommands(package_path, zip, pipe_write.get(), &args)
+                : SetUpNonAbUpdateCommands(package_path, zip, retry_count, pipe_write.get(), &args);
       !setup_result) {
     log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
     return INSTALL_CORRUPT;
@@ -484,11 +491,11 @@
   }
   if (WIFEXITED(status)) {
     if (WEXITSTATUS(status) != EXIT_SUCCESS) {
-      LOG(ERROR) << "Error in " << package << " (status " << WEXITSTATUS(status) << ")";
+      LOG(ERROR) << "Error in " << package_path << " (status " << WEXITSTATUS(status) << ")";
       return INSTALL_ERROR;
     }
   } else if (WIFSIGNALED(status)) {
-    LOG(ERROR) << "Error in " << package << " (killed by signal " << WTERMSIG(status) << ")";
+    LOG(ERROR) << "Error in " << package_path << " (killed by signal " << WTERMSIG(status) << ")";
     return INSTALL_ERROR;
   } else {
     LOG(FATAL) << "Invalid status code " << status;
@@ -497,7 +504,7 @@
   return INSTALL_SUCCESS;
 }
 
-// Verifes the compatibility info in a Treble-compatible package. Returns true directly if the
+// Verifies the compatibility info in a Treble-compatible package. Returns true directly if the
 // entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA
 // package.
 bool verify_package_compatibility(ZipArchiveHandle package_zip) {
@@ -564,37 +571,16 @@
   return false;
 }
 
-static InstallResult VerifyAndInstallPackage(const std::string& path, bool* wipe_cache,
-                                             bool needs_mount, std::vector<std::string>* log_buffer,
-                                             int retry_count, int* max_temperature,
-                                             RecoveryUI* ui) {
+static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache,
+                                             std::vector<std::string>* log_buffer, int retry_count,
+                                             int* max_temperature, RecoveryUI* ui) {
   ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
-  ui->Print("Finding update package...\n");
   // Give verification half the progress bar...
   ui->SetProgressType(RecoveryUI::DETERMINATE);
   ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
-  LOG(INFO) << "Update location: " << path;
-
-  // Map the update package into memory.
-  ui->Print("Opening update package...\n");
-
-  if (needs_mount) {
-    if (path[0] == '@') {
-      ensure_path_mounted(path.substr(1));
-    } else {
-      ensure_path_mounted(path);
-    }
-  }
-
-  auto package = Package::CreateMemoryPackage(
-      path, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
-  if (!package) {
-    log_buffer->push_back(android::base::StringPrintf("error: %d", kMapFileFailure));
-    return INSTALL_CORRUPT;
-  }
 
   // Verify package.
-  if (!verify_package(package.get(), ui)) {
+  if (!verify_package(package, ui)) {
     log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
     return INSTALL_CORRUPT;
   }
@@ -618,18 +604,15 @@
     ui->Print("Retry attempt: %d\n", retry_count);
   }
   ui->SetEnableReboot(false);
-  auto result =
-      TryUpdateBinary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui);
+  auto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui);
   ui->SetEnableReboot(true);
   ui->Print("\n");
 
   return result;
 }
 
-InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bool needs_mount,
-                             int retry_count, RecoveryUI* ui) {
-  CHECK(!path.empty());
-
+InstallResult InstallPackage(Package* package, const std::string_view package_id,
+                             bool should_wipe_cache, int retry_count, RecoveryUI* ui) {
   auto start = std::chrono::system_clock::now();
 
   int start_temperature = GetMaxValueFromThermalZone();
@@ -637,13 +620,19 @@
 
   InstallResult result;
   std::vector<std::string> log_buffer;
-  if (setup_install_mounts() != 0) {
+
+  ui->Print("Finding update package...\n");
+  LOG(INFO) << "Update package id: " << package_id;
+  if (!package) {
+    log_buffer.push_back(android::base::StringPrintf("error: %d", kMapFileFailure));
+    result = INSTALL_CORRUPT;
+  } else if (setup_install_mounts() != 0) {
     LOG(ERROR) << "failed to set up expected mounts for install; aborting";
     result = INSTALL_ERROR;
   } else {
     bool updater_wipe_cache = false;
-    result = VerifyAndInstallPackage(path, &updater_wipe_cache, needs_mount, &log_buffer,
-                                     retry_count, &max_temperature, ui);
+    result = VerifyAndInstallPackage(package, &updater_wipe_cache, &log_buffer, retry_count,
+                                     &max_temperature, ui);
     should_wipe_cache = should_wipe_cache || updater_wipe_cache;
   }
 
@@ -671,7 +660,7 @@
 
   // The first two lines need to be the package name and install result.
   std::vector<std::string> log_header = {
-    path,
+    std::string(package_id),
     result == INSTALL_SUCCESS ? "1" : "0",
     "time_total: " + std::to_string(time_total),
     "retry: " + std::to_string(retry_count),
diff --git a/install/package.cpp b/install/package.cpp
index 4402f48..86fc064 100644
--- a/install/package.cpp
+++ b/install/package.cpp
@@ -40,12 +40,20 @@
 
   ~MemoryPackage() override;
 
+  PackageType GetType() const override {
+    return PackageType::kMemory;
+  }
+
   // Memory maps the package file if necessary. Initializes the start address and size of the
   // package.
   uint64_t GetPackageSize() const override {
     return package_size_;
   }
 
+  std::string GetPath() const override {
+    return path_;
+  }
+
   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
 
   ZipArchiveHandle GetZipArchiveHandle() override;
@@ -82,10 +90,18 @@
 
   ~FilePackage() override;
 
+  PackageType GetType() const override {
+    return PackageType::kFile;
+  }
+
   uint64_t GetPackageSize() const override {
     return package_size_;
   }
 
+  std::string GetPath() const override {
+    return path_;
+  }
+
   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
 
   ZipArchiveHandle GetZipArchiveHandle() override;
@@ -253,7 +269,7 @@
     return zip_handle_;
   }
 
-  if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) {
+  if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_, false); err != 0) {
     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
     return nullptr;
   }
diff --git a/recovery.cpp b/recovery.cpp
index eb0c2b2..db66ea7 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -732,7 +732,15 @@
         set_retry_bootloader_message(retry_count + 1, args);
       }
 
-      status = InstallPackage(update_package, should_wipe_cache, true, retry_count, ui);
+      if (update_package[0] == '@') {
+        ensure_path_mounted(update_package + 1);
+      } else {
+        ensure_path_mounted(update_package);
+      }
+      // TODO(xunchang) install package from fuse for large packages on ILP32 builds.
+      auto package = Package::CreateMemoryPackage(
+          update_package, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
+      status = InstallPackage(package.get(), update_package, should_wipe_cache, retry_count, ui);
       if (status != INSTALL_SUCCESS) {
         ui->Print("Installation aborted.\n");