Call ioctl before each write on retry

If the update is a retry, ioctl(BLKDISCARD) the destination blocks before
writing to these blocks.

Bug: 28990135
Change-Id: I1e703808e68ebb1292cd66afd76be8fd6946ee59
diff --git a/install.cpp b/install.cpp
index 5732852..d5c5583 100644
--- a/install.cpp
+++ b/install.cpp
@@ -56,7 +56,7 @@
 // If the package contains an update binary, extract it and run it.
 static int
 try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache,
-                  std::vector<std::string>& log_buffer)
+                  std::vector<std::string>& log_buffer, int retry_count)
 {
     const ZipEntry* binary_entry =
             mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
@@ -130,15 +130,19 @@
     //
     //   - the name of the package zip file.
     //
+    //   - an optional argument "retry" if this update is a retry of a failed
+    //   update attempt.
+    //
 
-    const char** args = (const char**)malloc(sizeof(char*) * 5);
+    const char** args = (const char**)malloc(sizeof(char*) * 6);
     args[0] = binary;
     args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
     char* temp = (char*)malloc(10);
     sprintf(temp, "%d", pipefd[1]);
     args[2] = temp;
     args[3] = (char*)path;
-    args[4] = NULL;
+    args[4] = retry_count > 0 ? "retry" : NULL;
+    args[5] = NULL;
 
     pid_t pid = fork();
     if (pid == 0) {
@@ -215,7 +219,7 @@
 
 static int
 really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
-                       std::vector<std::string>& log_buffer)
+                       std::vector<std::string>& log_buffer, int retry_count)
 {
     ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
     ui->Print("Finding update package...\n");
@@ -276,8 +280,11 @@
 
     // Verify and install the contents of the package.
     ui->Print("Installing update...\n");
+    if (retry_count > 0) {
+        ui->Print("Retry attempt: %d\n", retry_count);
+    }
     ui->SetEnableReboot(false);
-    int result = try_update_binary(path, &zip, wipe_cache, log_buffer);
+    int result = try_update_binary(path, &zip, wipe_cache, log_buffer, retry_count);
     ui->SetEnableReboot(true);
     ui->Print("\n");
 
@@ -306,7 +313,7 @@
         LOGE("failed to set up expected mounts for install; aborting\n");
         result = INSTALL_ERROR;
     } else {
-        result = really_install_package(path, wipe_cache, needs_mount, log_buffer);
+        result = really_install_package(path, wipe_cache, needs_mount, log_buffer, retry_count);
     }
     if (install_log != nullptr) {
         fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);