Check the results from applypatch
am: 31f8cc84cf

Change-Id: Ie50652158b65d723346ffff18c85cbaab11820e1
diff --git a/Android.mk b/Android.mk
index 65d123a..9a064f2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -93,6 +93,10 @@
     LOCAL_STATIC_LIBRARIES += libext4_utils_static libz
 endif
 
+ifeq ($(AB_OTA_UPDATER),true)
+    LOCAL_CFLAGS += -DAB_OTA_UPDATER=1
+endif
+
 LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
 
 ifeq ($(TARGET_RECOVERY_UI_LIB),)
diff --git a/device.cpp b/device.cpp
index 2465b07..f8fbb8a 100644
--- a/device.cpp
+++ b/device.cpp
@@ -16,6 +16,29 @@
 
 #include "device.h"
 
+#if defined(AB_OTA_UPDATER)
+
+static const char* MENU_ITEMS[] = {
+    "Reboot system now",
+    "Reboot to bootloader",
+    "Wipe data/factory reset",
+    "Mount /system",
+    "Run graphics test",
+    "Power off",
+    NULL,
+};
+
+static const Device::BuiltinAction MENU_ACTIONS[] = {
+    Device::REBOOT,
+    Device::REBOOT_BOOTLOADER,
+    Device::WIPE_DATA,
+    Device::MOUNT_SYSTEM,
+    Device::RUN_GRAPHICS_TEST,
+    Device::SHUTDOWN,
+};
+
+#else
+
 static const char* MENU_ITEMS[] = {
     "Reboot system now",
     "Reboot to bootloader",
@@ -27,27 +50,30 @@
     "View recovery logs",
     "Run graphics test",
     "Power off",
-    NULL
+    NULL,
 };
 
+static const Device::BuiltinAction MENU_ACTIONS[] = {
+    Device::REBOOT,
+    Device::REBOOT_BOOTLOADER,
+    Device::APPLY_ADB_SIDELOAD,
+    Device::APPLY_SDCARD,
+    Device::WIPE_DATA,
+    Device::WIPE_CACHE,
+    Device::MOUNT_SYSTEM,
+    Device::VIEW_RECOVERY_LOGS,
+    Device::RUN_GRAPHICS_TEST,
+    Device::SHUTDOWN,
+};
+
+#endif
+
 const char* const* Device::GetMenuItems() {
   return MENU_ITEMS;
 }
 
 Device::BuiltinAction Device::InvokeMenuItem(int menu_position) {
-  switch (menu_position) {
-    case 0: return REBOOT;
-    case 1: return REBOOT_BOOTLOADER;
-    case 2: return APPLY_ADB_SIDELOAD;
-    case 3: return APPLY_SDCARD;
-    case 4: return WIPE_DATA;
-    case 5: return WIPE_CACHE;
-    case 6: return MOUNT_SYSTEM;
-    case 7: return VIEW_RECOVERY_LOGS;
-    case 8: return RUN_GRAPHICS_TEST;
-    case 9: return SHUTDOWN;
-    default: return NO_ACTION;
-  }
+  return menu_position < 0 ? NO_ACTION : MENU_ACTIONS[menu_position];
 }
 
 int Device::HandleMenuKey(int key, int visible) {
diff --git a/recovery.cpp b/recovery.cpp
index 6b6643f..65e1a7b 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -19,7 +19,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <inttypes.h>
 #include <limits.h>
+#include <linux/fs.h>
 #include <linux/input.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -33,12 +35,15 @@
 #include <unistd.h>
 
 #include <chrono>
+#include <string>
+#include <vector>
 
 #include <adb.h>
 #include <android/log.h> /* Android Log Priority Tags */
 #include <android-base/file.h>
 #include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <cutils/android_reboot.h>
 #include <cutils/properties.h>
 #include <log/logger.h> /* Android Log packet format */
@@ -58,6 +63,7 @@
 #include "minzip/DirUtil.h"
 #include "roots.h"
 #include "ui.h"
+#include "unique_fd.h"
 #include "screen_ui.h"
 
 struct selabel_handle *sehandle;
@@ -77,6 +83,7 @@
   { "shutdown_after", no_argument, NULL, 'p' },
   { "reason", required_argument, NULL, 'r' },
   { "security", no_argument, NULL, 'e'},
+  { "wipe_ab", no_argument, NULL, 0 },
   { NULL, 0, NULL, 0 },
 };
 
@@ -103,6 +110,7 @@
 // So we should check battery with a slightly lower limitation.
 static const int BATTERY_OK_PERCENTAGE = 20;
 static const int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15;
+constexpr const char* RECOVERY_WIPE = "/etc/recovery.wipe";
 
 RecoveryUI* ui = NULL;
 static const char* locale = "en_US";
@@ -853,6 +861,75 @@
     return success;
 }
 
+// Secure-wipe a given partition. It uses BLKSECDISCARD, if supported.
+// Otherwise, it goes with BLKDISCARD (if device supports BLKDISCARDZEROES) or
+// BLKZEROOUT.
+static bool secure_wipe_partition(const std::string& partition) {
+    unique_fd fd(TEMP_FAILURE_RETRY(open(partition.c_str(), O_WRONLY)));
+    if (fd.get() == -1) {
+        LOGE("failed to open \"%s\": %s\n", partition.c_str(), strerror(errno));
+        return false;
+    }
+
+    uint64_t range[2] = {0, 0};
+    if (ioctl(fd.get(), BLKGETSIZE64, &range[1]) == -1 || range[1] == 0) {
+        LOGE("failed to get partition size: %s\n", strerror(errno));
+        return false;
+    }
+    printf("Secure-wiping \"%s\" from %" PRIu64 " to %" PRIu64 ".\n",
+           partition.c_str(), range[0], range[1]);
+
+    printf("Trying BLKSECDISCARD...\t");
+    if (ioctl(fd.get(), BLKSECDISCARD, &range) == -1) {
+        printf("failed: %s\n", strerror(errno));
+
+        // Use BLKDISCARD if it zeroes out blocks, otherwise use BLKZEROOUT.
+        unsigned int zeroes;
+        if (ioctl(fd.get(), BLKDISCARDZEROES, &zeroes) == 0 && zeroes != 0) {
+            printf("Trying BLKDISCARD...\t");
+            if (ioctl(fd.get(), BLKDISCARD, &range) == -1) {
+                printf("failed: %s\n", strerror(errno));
+                return false;
+            }
+        } else {
+            printf("Trying BLKZEROOUT...\t");
+            if (ioctl(fd.get(), BLKZEROOUT, &range) == -1) {
+                printf("failed: %s\n", strerror(errno));
+                return false;
+            }
+        }
+    }
+
+    printf("done\n");
+    return true;
+}
+
+// Wipe the current A/B device, with a secure wipe of all the partitions in
+// RECOVERY_WIPE.
+static bool wipe_ab_device() {
+    ui->SetBackground(RecoveryUI::ERASING);
+    ui->SetProgressType(RecoveryUI::INDETERMINATE);
+
+    std::string partition_list;
+    if (!android::base::ReadFileToString(RECOVERY_WIPE, &partition_list)) {
+        LOGE("failed to read \"%s\".\n", RECOVERY_WIPE);
+        return false;
+    }
+
+    std::vector<std::string> lines = android::base::Split(partition_list, "\n");
+    for (const std::string& line : lines) {
+        std::string partition = android::base::Trim(line);
+        // Ignore '#' comment or empty lines.
+        if (android::base::StartsWith(partition, "#") || partition.empty()) {
+            continue;
+        }
+
+        // Proceed anyway even if it fails to wipe some partition.
+        secure_wipe_partition(partition);
+    }
+    return true;
+}
+
 static void choose_recovery_file(Device* device) {
     if (!has_cache) {
         ui->Print("No /cache partition found.\n");
@@ -1340,6 +1417,7 @@
     const char *update_package = NULL;
     bool should_wipe_data = false;
     bool should_wipe_cache = false;
+    bool should_wipe_ab = false;
     bool show_text = false;
     bool sideload = false;
     bool sideload_auto_reboot = false;
@@ -1349,7 +1427,8 @@
     bool security_update = false;
 
     int arg;
-    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
+    int option_index;
+    while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
         switch (arg) {
         case 'i': send_intent = optarg; break;
         case 'n': android::base::ParseInt(optarg, &retry_count, 0); break;
@@ -1372,6 +1451,13 @@
         case 'p': shutdown_after = true; break;
         case 'r': reason = optarg; break;
         case 'e': security_update = true; break;
+        case 0: {
+            if (strcmp(OPTIONS[option_index].name, "wipe_ab") == 0) {
+                should_wipe_ab = true;
+                break;
+            }
+            break;
+        }
         case '?':
             LOGE("Invalid command argument\n");
             continue;
@@ -1510,6 +1596,10 @@
         if (!wipe_cache(false, device)) {
             status = INSTALL_ERROR;
         }
+    } else if (should_wipe_ab) {
+        if (!wipe_ab_device()) {
+            status = INSTALL_ERROR;
+        }
     } else if (sideload) {
         // 'adb reboot sideload' acts the same as user presses key combinations
         // to enter the sideload mode. When 'sideload-auto-reboot' is used, text
diff --git a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml
index c2d8f22..6f433e3 100644
--- a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml
+++ b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="recovery_installing" msgid="2013591905463558223">"Ažuriranje sistema se instalira"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"Briše se"</string>
-    <string name="recovery_no_command" msgid="4465476568623024327">"Nema komande"</string>
+    <string name="recovery_installing" msgid="4995089002339765600">"Instaliranje ažuriranja sistema..."</string>
+    <string name="recovery_erasing" msgid="3454811999717520920">"Brisanje..."</string>
+    <string name="recovery_no_command" msgid="3005798864326873414">"Nema komande."</string>
     <string name="recovery_error" msgid="5748178989622716736">"Greška!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"Instalira se bezbednosno ažuriranje"</string>
+    <string name="recovery_installing_security" msgid="241961948312007086">"Instalira se bezbednosno ažuriranje…"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-be-rBY/strings.xml b/tools/recovery_l10n/res/values-be-rBY/strings.xml
index 7c0954d..5decf81 100644
--- a/tools/recovery_l10n/res/values-be-rBY/strings.xml
+++ b/tools/recovery_l10n/res/values-be-rBY/strings.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="recovery_installing" msgid="2013591905463558223">"Усталёўка абнаўлення сістэмы"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"Сціранне"</string>
-    <string name="recovery_no_command" msgid="4465476568623024327">"Няма каманды"</string>
+    <string name="recovery_installing" msgid="4995089002339765600">"Усталёўка абнаўлення сістэмы..."</string>
+    <string name="recovery_erasing" msgid="3454811999717520920">"Выдаленне..."</string>
+    <string name="recovery_no_command" msgid="3005798864326873414">"Няма каманды"</string>
     <string name="recovery_error" msgid="5748178989622716736">"Памылка"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"Усталёўка абнаўлення сістэмы бяспекі"</string>
+    <string name="recovery_installing_security" msgid="241961948312007086">"Усталёўка абнаўлення сістэмы бяспекі..."</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-bs-rBA/strings.xml b/tools/recovery_l10n/res/values-bs-rBA/strings.xml
index 412cf02..8b6202a 100644
--- a/tools/recovery_l10n/res/values-bs-rBA/strings.xml
+++ b/tools/recovery_l10n/res/values-bs-rBA/strings.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="recovery_installing" msgid="2013591905463558223">"Ažuriranje sistema…"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"Brisanje u toku"</string>
-    <string name="recovery_no_command" msgid="4465476568623024327">"Nema komande"</string>
+    <string name="recovery_installing" msgid="4995089002339765600">"Sistem se ažurira…"</string>
+    <string name="recovery_erasing" msgid="3454811999717520920">"Briše se…"</string>
+    <string name="recovery_no_command" msgid="3005798864326873414">"Nema komande."</string>
     <string name="recovery_error" msgid="5748178989622716736">"Greška!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"Instaliranje sigurnosnog ažuriranja…"</string>
+    <string name="recovery_installing_security" msgid="241961948312007086">"Instaliranje sigurnosnog ažuriranja…"</string>
 </resources>