Merge "applypatch: add -fPIC for libimgpatch in Chrome OS."
diff --git a/Android.mk b/Android.mk
index 4477fef..fc981e1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,18 +14,20 @@
 
 LOCAL_PATH := $(call my-dir)
 
+# libfusesideload (static library)
+# ===============================
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := fuse_sideload.cpp
 LOCAL_CLANG := true
 LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
 LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
-
 LOCAL_MODULE := libfusesideload
-
 LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt
 include $(BUILD_STATIC_LIBRARY)
 
+# recovery (static executable)
+# ===============================
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
@@ -102,7 +104,8 @@
 
 include $(BUILD_EXECUTABLE)
 
-# All the APIs for testing
+# libverifier (static library)
+# ===============================
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_MODULE := libverifier
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 90a86dc..9e64718 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -14,59 +14,83 @@
 
 LOCAL_PATH := $(call my-dir)
 
+# libapplypatch (static library)
+# ===============================
 include $(CLEAR_VARS)
-
 LOCAL_CLANG := true
-LOCAL_SRC_FILES := applypatch.cpp bspatch.cpp freecache.cpp imgpatch.cpp utils.cpp
+LOCAL_SRC_FILES := \
+    applypatch.cpp \
+    bspatch.cpp \
+    freecache.cpp \
+    imgpatch.cpp \
+    utils.cpp
 LOCAL_MODULE := libapplypatch
 LOCAL_MODULE_TAGS := eng
-LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libcrypto_static libbz libz
-
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/include \
+    bootable/recovery
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES += \
+    libotafault \
+    libmtdutils \
+    libbase \
+    libcrypto_static \
+    libbz \
+    libz
 include $(BUILD_STATIC_LIBRARY)
 
+# libimgpatch (static library)
+# ===============================
 include $(CLEAR_VARS)
-
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
 LOCAL_MODULE := libimgpatch
-LOCAL_C_INCLUDES += bootable/recovery
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/include \
+    bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
-
 include $(BUILD_STATIC_LIBRARY)
 
-ifeq ($(HOST_OS),linux)
+# libimgpatch (host static library)
+# ===============================
 include $(CLEAR_VARS)
-
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
 LOCAL_MODULE := libimgpatch
-LOCAL_C_INCLUDES += bootable/recovery
+LOCAL_MODULE_HOST_OS := linux
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/include \
+    bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
-
 include $(BUILD_HOST_STATIC_LIBRARY)
-endif  # HOST_OS == linux
 
+# applypatch (executable)
+# ===============================
 include $(CLEAR_VARS)
-
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := main.cpp
 LOCAL_MODULE := applypatch
 LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz libedify
+LOCAL_STATIC_LIBRARIES += \
+    libapplypatch \
+    libbase \
+    libedify \
+    libotafault \
+    libminzip \
+    libmtdutils \
+    libcrypto_static \
+    libbz
 LOCAL_SHARED_LIBRARIES += libz libcutils libc
-
 include $(BUILD_EXECUTABLE)
 
+# imgdiff (host static executable)
+# ===============================
 include $(CLEAR_VARS)
-
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := imgdiff.cpp utils.cpp bsdiff.cpp
 LOCAL_MODULE := imgdiff
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_C_INCLUDES += external/zlib external/bzip2
 LOCAL_STATIC_LIBRARIES += libz libbz
-
+LOCAL_FORCE_STATIC_EXECUTABLE := true
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 6445159..c8594c2 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -31,7 +31,7 @@
 #include <android-base/strings.h>
 
 #include "openssl/sha.h"
-#include "applypatch.h"
+#include "applypatch/applypatch.h"
 #include "mtdutils/mtdutils.h"
 #include "edify/expr.h"
 #include "ota_io.h"
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index 1fc1455..a4945da 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -30,7 +30,7 @@
 #include <bzlib.h>
 
 #include "openssl/sha.h"
-#include "applypatch.h"
+#include "applypatch/applypatch.h"
 
 void ShowBSDiffLicense() {
     puts("The bsdiff library used herein is:\n"
diff --git a/applypatch/freecache.cpp b/applypatch/freecache.cpp
index c84f427..331cae2 100644
--- a/applypatch/freecache.cpp
+++ b/applypatch/freecache.cpp
@@ -32,7 +32,7 @@
 #include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 
-#include "applypatch.h"
+#include "applypatch/applypatch.h"
 
 static int EliminateOpenFiles(std::set<std::string>* files) {
   std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir);
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 0ab995b..4251c01 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -28,7 +28,7 @@
 
 #include "zlib.h"
 #include "openssl/sha.h"
-#include "applypatch.h"
+#include "applypatch/applypatch.h"
 #include "imgdiff.h"
 #include "utils.h"
 
diff --git a/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h
similarity index 100%
rename from applypatch/applypatch.h
rename to applypatch/include/applypatch/applypatch.h
diff --git a/applypatch/main.cpp b/applypatch/main.cpp
index 9013760..0ff8cbf 100644
--- a/applypatch/main.cpp
+++ b/applypatch/main.cpp
@@ -22,7 +22,7 @@
 #include <memory>
 #include <vector>
 
-#include "applypatch.h"
+#include "applypatch/applypatch.h"
 #include "edify/expr.h"
 #include "openssl/sha.h"
 
diff --git a/etc/init.rc b/etc/init.rc
index dc18659..5915b8d 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -1,6 +1,9 @@
 import /init.recovery.${ro.hardware}.rc
 
 on early-init
+    # Set the security context of /postinstall if present.
+    restorecon /postinstall
+
     start ueventd
     start healthd
 
diff --git a/install.cpp b/install.cpp
index 33c1f54..144a353 100644
--- a/install.cpp
+++ b/install.cpp
@@ -144,6 +144,7 @@
     close(pipefd[1]);
 
     *wipe_cache = false;
+    bool retry_update = false;
 
     char buffer[1024];
     FILE* from_child = fdopen(pipefd[0], "r");
@@ -180,6 +181,8 @@
             // to be able to reboot during installation (useful for
             // debugging packages that don't exit).
             ui->SetEnableReboot(true);
+        } else if (strcmp(command, "retry_update") == 0) {
+            retry_update = true;
         } else {
             LOGE("unknown command [%s]\n", command);
         }
@@ -188,6 +191,9 @@
 
     int status;
     waitpid(pid, &status, 0);
+    if (retry_update) {
+        return INSTALL_RETRY;
+    }
     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
         LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
         return INSTALL_ERROR;
diff --git a/install.h b/install.h
index f92f061..fd08e3c 100644
--- a/install.h
+++ b/install.h
@@ -23,7 +23,8 @@
 extern "C" {
 #endif
 
-enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SKIPPED };
+enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SKIPPED,
+        INSTALL_RETRY };
 // Install the package specified by root_path.  If INSTALL_SUCCESS is
 // returned and *wipe_cache is true on exit, caller should wipe the
 // cache partition.
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 997e9ca..0788f75 100644
--- a/minui/graphics_fbdev.cpp
+++ b/minui/graphics_fbdev.cpp
@@ -176,18 +176,6 @@
 
 static GRSurface* fbdev_flip(minui_backend* backend __unused) {
     if (double_buffered) {
-#if defined(RECOVERY_BGRA)
-        // In case of BGRA, do some byte swapping
-        unsigned int idx;
-        unsigned char tmp;
-        unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
-        for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
-                idx += 4) {
-            tmp = ucfb_vaddr[idx];
-            ucfb_vaddr[idx    ] = ucfb_vaddr[idx + 2];
-            ucfb_vaddr[idx + 2] = tmp;
-        }
-#endif
         // Change gr_draw to point to the buffer currently displayed,
         // then flip the driver so we're displaying the other buffer
         // instead.
diff --git a/otafault/Android.mk b/otafault/Android.mk
index 7468de6..52d7067 100644
--- a/otafault/Android.mk
+++ b/otafault/Android.mk
@@ -14,29 +14,34 @@
 
 LOCAL_PATH := $(call my-dir)
 
+# otafault (static library)
+# ===============================
 include $(CLEAR_VARS)
 
 otafault_static_libs := \
     libminzip \
-    libz \
     libselinux \
+    libz
 
 LOCAL_SRC_FILES := config.cpp ota_io.cpp
-LOCAL_MODULE_TAGS := eng
 LOCAL_MODULE := libotafault
 LOCAL_CLANG := true
 LOCAL_C_INCLUDES := bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_WHOLE_STATIC_LIBRARIES := $(otafault_static_libs)
+LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
 
 include $(BUILD_STATIC_LIBRARY)
 
+# otafault_test (static executable)
+# ===============================
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := config.cpp ota_io.cpp test.cpp
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := otafault_test
-LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
+LOCAL_STATIC_LIBRARIES := \
+    libotafault \
+    $(otafault_static_libs)
 LOCAL_C_INCLUDES := bootable/recovery
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 
diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp
index 2ce3dfc..dd805e5 100644
--- a/otafault/ota_io.cpp
+++ b/otafault/ota_io.cpp
@@ -29,6 +29,7 @@
 static std::string read_fault_file_name = "";
 static std::string write_fault_file_name = "";
 static std::string fsync_fault_file_name = "";
+bool have_eio_error = false;
 
 static bool get_hit_file(const char* cached_path, std::string ffn) {
     return should_hit_cache()
@@ -85,10 +86,16 @@
                 get_hit_file(cached_path, read_fault_file_name)) {
             read_fault_file_name = "";
             errno = EIO;
+            have_eio_error = true;
             return 0;
         }
     }
-    return fread(ptr, size, nitems, stream);
+    size_t status = fread(ptr, size, nitems, stream);
+    // If I/O error occurs, set the retry-update flag.
+    if (status != nitems && errno == EIO) {
+        have_eio_error = true;
+    }
+    return status;
 }
 
 ssize_t ota_read(int fd, void* buf, size_t nbyte) {
@@ -99,10 +106,15 @@
                 && get_hit_file(cached_path, read_fault_file_name)) {
             read_fault_file_name = "";
             errno = EIO;
+            have_eio_error = true;
             return -1;
         }
     }
-    return read(fd, buf, nbyte);
+    ssize_t status = read(fd, buf, nbyte);
+    if (status == -1 && errno == EIO) {
+        have_eio_error = true;
+    }
+    return status;
 }
 
 size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
@@ -113,10 +125,15 @@
                 get_hit_file(cached_path, write_fault_file_name)) {
             write_fault_file_name = "";
             errno = EIO;
+            have_eio_error = true;
             return 0;
         }
     }
-    return fwrite(ptr, size, count, stream);
+    size_t status = fwrite(ptr, size, count, stream);
+    if (status != count && errno == EIO) {
+        have_eio_error = true;
+    }
+    return status;
 }
 
 ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
@@ -127,10 +144,15 @@
                 get_hit_file(cached_path, write_fault_file_name)) {
             write_fault_file_name = "";
             errno = EIO;
+            have_eio_error = true;
             return -1;
         }
     }
-    return write(fd, buf, nbyte);
+    ssize_t status = write(fd, buf, nbyte);
+    if (status == -1 && errno == EIO) {
+        have_eio_error = true;
+    }
+    return status;
 }
 
 int ota_fsync(int fd) {
@@ -141,9 +163,14 @@
                 get_hit_file(cached_path, fsync_fault_file_name)) {
             fsync_fault_file_name = "";
             errno = EIO;
+            have_eio_error = true;
             return -1;
         }
     }
-    return fsync(fd);
+    int status = fsync(fd);
+    if (status == -1 && errno == EIO) {
+        have_eio_error = true;
+    }
+    return status;
 }
 
diff --git a/recovery.cpp b/recovery.cpp
index 3ce2185..6781fa4 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -36,6 +36,7 @@
 
 #include <adb.h>
 #include <android-base/file.h>
+#include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 #include <cutils/android_reboot.h>
 #include <cutils/properties.h>
@@ -60,6 +61,7 @@
 static const struct option OPTIONS[] = {
   { "send_intent", required_argument, NULL, 'i' },
   { "update_package", required_argument, NULL, 'u' },
+  { "retry_count", required_argument, NULL, 'n' },
   { "wipe_data", no_argument, NULL, 'w' },
   { "wipe_cache", no_argument, NULL, 'c' },
   { "show_text", no_argument, NULL, 't' },
@@ -86,6 +88,7 @@
 static const char *LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
 static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
 static const int KEEP_LOG_COUNT = 10;
+static const int EIO_RETRY_COUNT = 2;
 static const int BATTERY_READ_TIMEOUT_IN_SEC = 10;
 // GmsCore enters recovery mode to install package when having enough battery
 // percentage. Normally, the threshold is 40% without charger and 20% with charger.
@@ -98,6 +101,7 @@
 char* stage = NULL;
 char* reason = NULL;
 bool modified_flash = false;
+static bool has_cache = false;
 
 /*
  * The recovery tool communicates with the main system through /cache files.
@@ -310,8 +314,8 @@
         }
     }
 
-    // --- if that doesn't work, try the command file
-    if (*argc <= 1) {
+    // --- if that doesn't work, try the command file (if we have /cache).
+    if (*argc <= 1 && has_cache) {
         FILE *fp = fopen_path(COMMAND_FILE, "r");
         if (fp != NULL) {
             char *token;
@@ -433,6 +437,11 @@
 }
 
 static void copy_logs() {
+    // We can do nothing for now if there's no /cache partition.
+    if (!has_cache) {
+        return;
+    }
+
     // We only rotate and record the log of the current session if there are
     // actual attempts to modify the flash, such as wipes, installs from BCB
     // or menu selections. This is to avoid unnecessary rotation (and
@@ -464,7 +473,7 @@
 static void
 finish_recovery(const char *send_intent) {
     // By this point, we're ready to return to the main system...
-    if (send_intent != NULL) {
+    if (send_intent != NULL && has_cache) {
         FILE *fp = fopen_path(INTENT_FILE, "w");
         if (fp == NULL) {
             LOGE("Can't open %s\n", INTENT_FILE);
@@ -477,7 +486,7 @@
     // Save the locale to cache, so if recovery is next started up
     // without a --locale argument (eg, directly from the bootloader)
     // it will use the last-known locale.
-    if (locale != NULL) {
+    if (locale != NULL && has_cache) {
         LOGI("Saving locale \"%s\"\n", locale);
         FILE* fp = fopen_path(LOCALE_FILE, "w");
         fwrite(locale, 1, strlen(locale), fp);
@@ -494,12 +503,13 @@
     set_bootloader_message(&boot);
 
     // Remove the command file, so recovery won't repeat indefinitely.
-    if (ensure_path_mounted(COMMAND_FILE) != 0 ||
-        (unlink(COMMAND_FILE) && errno != ENOENT)) {
-        LOGW("Can't unlink %s\n", COMMAND_FILE);
+    if (has_cache) {
+        if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) {
+            LOGW("Can't unlink %s\n", COMMAND_FILE);
+        }
+        ensure_path_unmounted(CACHE_ROOT);
     }
 
-    ensure_path_unmounted(CACHE_ROOT);
     sync();  // For good measure.
 }
 
@@ -768,7 +778,7 @@
     bool success =
         device->PreWipeData() &&
         erase_volume("/data") &&
-        erase_volume("/cache") &&
+        (has_cache ? erase_volume("/cache") : true) &&
         device->PostWipeData();
     ui->Print("Data wipe %s.\n", success ? "complete" : "failed");
     return success;
@@ -776,6 +786,11 @@
 
 // Return true on success.
 static bool wipe_cache(bool should_confirm, Device* device) {
+    if (!has_cache) {
+        ui->Print("No /cache partition found.\n");
+        return false;
+    }
+
     if (should_confirm && !yes_no(device, "Wipe cache?", "  THIS CAN NOT BE UNDONE!")) {
         return false;
     }
@@ -789,6 +804,11 @@
 }
 
 static void choose_recovery_file(Device* device) {
+    if (!has_cache) {
+        ui->Print("No /cache partition found.\n");
+        return;
+    }
+
     // "Back" + KEEP_LOG_COUNT * 2 + terminating nullptr entry
     char* entries[1 + KEEP_LOG_COUNT * 2 + 1];
     memset(entries, 0, sizeof(entries));
@@ -1120,6 +1140,29 @@
     }
 }
 
+static void set_retry_bootloader_message(int retry_count, int argc, char** argv) {
+    struct bootloader_message boot {};
+    strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
+    strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
+
+    for (int i = 1; i < argc; ++i) {
+        if (strstr(argv[i], "retry_count") == nullptr) {
+            strlcat(boot.recovery, argv[i], sizeof(boot.recovery));
+            strlcat(boot.recovery, "\n", sizeof(boot.recovery));
+        }
+    }
+
+    // Initialize counter to 1 if it's not in BCB, otherwise increment it by 1.
+    if (retry_count == 0) {
+        strlcat(boot.recovery, "--retry_count=1\n", sizeof(boot.recovery));
+    } else {
+        char buffer[20];
+        snprintf(buffer, sizeof(buffer), "--retry_count=%d\n", retry_count+1);
+        strlcat(boot.recovery, buffer, sizeof(boot.recovery));
+    }
+    set_bootloader_message(&boot);
+}
+
 int main(int argc, char **argv) {
     // If this binary is started with the single argument "--adbd",
     // instead of being the normal recovery binary, it turns into kind
@@ -1142,6 +1185,8 @@
     printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
 
     load_volume_table();
+    has_cache = volume_for_path(CACHE_ROOT) != nullptr;
+
     get_args(&argc, &argv);
 
     const char *send_intent = NULL;
@@ -1153,11 +1198,13 @@
     bool sideload_auto_reboot = false;
     bool just_exit = false;
     bool shutdown_after = false;
+    int retry_count = 0;
 
     int arg;
     while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
         switch (arg) {
         case 'i': send_intent = optarg; break;
+        case 'n': android::base::ParseInt(optarg, &retry_count, 0); break;
         case 'u': update_package = optarg; break;
         case 'w': should_wipe_data = true; break;
         case 'c': should_wipe_cache = true; break;
@@ -1182,7 +1229,7 @@
         }
     }
 
-    if (locale == NULL) {
+    if (locale == nullptr && has_cache) {
         load_locale_from_cache();
     }
     printf("locale is [%s]\n", locale);
@@ -1262,7 +1309,24 @@
             }
             if (status != INSTALL_SUCCESS) {
                 ui->Print("Installation aborted.\n");
+                // When I/O error happens, reboot and retry installation EIO_RETRY_COUNT
+                // times before we abandon this OTA update.
+                if (status == INSTALL_RETRY && retry_count < EIO_RETRY_COUNT) {
+                    copy_logs();
+                    set_retry_bootloader_message(retry_count, argc, argv);
+                    // Print retry count on screen.
+                    ui->Print("Retry attempt %d\n", retry_count);
 
+                    // Reboot and retry the update
+                    int ret = property_set(ANDROID_RB_PROPERTY, "reboot,recovery");
+                    if (ret < 0) {
+                        ui->Print("Reboot failed\n");
+                    } else {
+                        while (true) {
+                            pause();
+                        }
+                    }
+                }
                 // If this is an eng or userdebug build, then automatically
                 // turn the text display on if the script fails so the error
                 // message is visible.
diff --git a/updater/Android.mk b/updater/Android.mk
index d7aa613..47c56cc 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -14,26 +14,50 @@
 
 LOCAL_PATH := $(call my-dir)
 
-updater_src_files := \
-	install.cpp \
-	blockimg.cpp \
-	updater.cpp
-
-#
-# Build a statically-linked binary to include in OTA packages
-#
+# updater (static executable)
+# ===============================
+# Build a statically-linked binary to include in OTA packages.
 include $(CLEAR_VARS)
 
-# Build only in eng, so we don't end up with a copy of this in /system
-# on user builds.  (TODO: find a better way to build device binaries
-# needed only for OTA packages.)
-LOCAL_MODULE_TAGS := eng
+updater_src_files := \
+    install.cpp \
+    blockimg.cpp \
+    updater.cpp
 
 LOCAL_CLANG := true
-
 LOCAL_SRC_FILES := $(updater_src_files)
 
-LOCAL_STATIC_LIBRARIES += libfec libfec_rs libext4_utils_static libsquashfs_utils libcrypto_static
+LOCAL_STATIC_LIBRARIES += \
+    $(TARGET_RECOVERY_UPDATER_LIBS) \
+    $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS) \
+    libfec \
+    libfec_rs \
+    libext4_utils_static \
+    libsquashfs_utils \
+    libcrypto_static \
+    libapplypatch \
+    libbase \
+    libotafault \
+    libedify \
+    libmtdutils \
+    libminzip \
+    libz \
+    libbz \
+    libcutils \
+    liblog \
+    libselinux
+
+tune2fs_static_libraries := \
+    libext2_com_err \
+    libext2_blkid \
+    libext2_quota \
+    libext2_uuid_static \
+    libext2_e2p \
+    libext2fs
+
+LOCAL_STATIC_LIBRARIES += \
+    libtune2fs \
+    $(tune2fs_static_libraries)
 
 ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
 LOCAL_CFLAGS += -DUSE_EXT4
@@ -44,20 +68,6 @@
     libz
 endif
 
-LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libedify libmtdutils libminzip libz
-LOCAL_STATIC_LIBRARIES += libbz
-LOCAL_STATIC_LIBRARIES += libcutils liblog libc
-LOCAL_STATIC_LIBRARIES += libselinux
-tune2fs_static_libraries := \
- libext2_com_err \
- libext2_blkid \
- libext2_quota \
- libext2_uuid_static \
- libext2_e2p \
- libext2fs
-LOCAL_STATIC_LIBRARIES += libtune2fs $(tune2fs_static_libraries)
-
 LOCAL_C_INCLUDES += external/e2fsprogs/misc
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
 
diff --git a/updater/updater.cpp b/updater/updater.cpp
index efb4a8c..1693fa1 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -36,6 +36,8 @@
 // (Note it's "updateR-script", not the older "update-script".)
 #define SCRIPT_NAME "META-INF/com/google/android/updater-script"
 
+extern bool have_eio_error;
+
 struct selabel_handle *sehandle;
 
 int main(int argc, char** argv) {
@@ -141,6 +143,11 @@
     state.errmsg = NULL;
 
     char* result = Evaluate(&state, root);
+
+    if (have_eio_error) {
+        fprintf(cmd_pipe, "retry_update\n");
+    }
+
     if (result == NULL) {
         if (state.errmsg == NULL) {
             printf("script aborted (no error message)\n");