Snap for 4796633 from d0c3f62d3e002b82380b983b9e5c81c6662eea5b to qt-release

Change-Id: I1baaa6d8dee35cc11ec3f60c1f60ed99ce12b4ae
diff --git a/Android.mk b/Android.mk
index 09feba2..efd7462 100644
--- a/Android.mk
+++ b/Android.mk
@@ -97,61 +97,8 @@
 
 include $(BUILD_STATIC_LIBRARY)
 
-# librecovery (static library)
-# ===============================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    install.cpp
-
-LOCAL_CFLAGS := $(recovery_common_cflags)
-
-ifeq ($(AB_OTA_UPDATER),true)
-    LOCAL_CFLAGS += -DAB_OTA_UPDATER=1
-endif
-
-LOCAL_MODULE := librecovery
-
-LOCAL_STATIC_LIBRARIES := \
-    libminui \
-    libotautil \
-    libvintf_recovery \
-    libcrypto_utils \
-    libcrypto \
-    libbase \
-    libziparchive \
-
-include $(BUILD_STATIC_LIBRARY)
-
-# recovery (static executable)
-# ===============================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    adb_install.cpp \
-    fuse_sdcard_provider.cpp \
-    logging.cpp \
-    recovery.cpp \
-    recovery_main.cpp \
-    roots.cpp \
-
-LOCAL_MODULE := recovery
-
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
-
-# Cannot link with LLD: undefined symbol: UsbNoPermissionsLongHelpText
-# http://b/77543887, lld does not handle -Wl,--gc-sections as well as ld.
-LOCAL_USE_CLANG_LLD := false
-
-LOCAL_CFLAGS := $(recovery_common_cflags)
-
-LOCAL_C_INCLUDES += \
-    system/vold \
-
 # Health HAL dependency
-LOCAL_STATIC_LIBRARIES := \
+health_hal_static_libraries := \
     android.hardware.health@2.0-impl \
     android.hardware.health@2.0 \
     android.hardware.health@1.0 \
@@ -163,8 +110,7 @@
     libvndksupport \
     libbatterymonitor
 
-LOCAL_STATIC_LIBRARIES += \
-    librecovery \
+librecovery_static_libraries := \
     $(TARGET_RECOVERY_UI_LIB) \
     libbootloader_message \
     libfusesideload \
@@ -173,8 +119,8 @@
     libminui \
     libverifier \
     libotautil \
+    $(health_hal_static_libraries) \
     libasyncio \
-    libbatterymonitor \
     libcrypto_utils \
     libcrypto \
     libext4_utils \
@@ -193,6 +139,57 @@
     libselinux \
     libz \
 
+# librecovery (static library)
+# ===============================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    adb_install.cpp \
+    fuse_sdcard_provider.cpp \
+    install.cpp \
+    recovery.cpp \
+    roots.cpp \
+
+LOCAL_C_INCLUDES := \
+    system/vold \
+
+LOCAL_CFLAGS := $(recovery_common_cflags)
+
+ifeq ($(AB_OTA_UPDATER),true)
+    LOCAL_CFLAGS += -DAB_OTA_UPDATER=1
+endif
+
+LOCAL_MODULE := librecovery
+
+LOCAL_STATIC_LIBRARIES := \
+    $(librecovery_static_libraries)
+
+include $(BUILD_STATIC_LIBRARY)
+
+# recovery (static executable)
+# ===============================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    logging.cpp \
+    recovery_main.cpp \
+
+LOCAL_MODULE := recovery
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+
+# Cannot link with LLD: undefined symbol: UsbNoPermissionsLongHelpText
+# http://b/77543887, lld does not handle -Wl,--gc-sections as well as ld.
+LOCAL_USE_CLANG_LLD := false
+
+LOCAL_CFLAGS := $(recovery_common_cflags)
+
+LOCAL_STATIC_LIBRARIES := \
+    librecovery \
+    $(librecovery_static_libraries)
+
 LOCAL_HAL_STATIC_LIBRARIES := libhealthd
 
 LOCAL_REQUIRED_MODULES := \
diff --git a/recovery.cpp b/recovery.cpp
index ac3e7c6..69b1499 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1083,6 +1083,11 @@
     ui->SetStage(st_cur, st_max);
   }
 
+  std::vector<std::string> title_lines =
+      android::base::Split(android::base::GetProperty("ro.bootimage.build.fingerprint", ""), ":");
+  title_lines.insert(std::begin(title_lines), "Android Recovery");
+  ui->SetTitle(title_lines);
+
   device->StartRecovery();
 
   printf("Command:");
diff --git a/screen_ui.cpp b/screen_ui.cpp
index fd7a1be..f1b3878 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -496,6 +496,10 @@
   return offset;
 }
 
+void ScreenRecoveryUI::SetTitle(const std::vector<std::string>& lines) {
+  title_lines_ = lines;
+}
+
 // Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex
 // locked.
 void ScreenRecoveryUI::draw_screen_locked() {
@@ -529,11 +533,9 @@
     int x = kMarginWidth + kMenuIndent;
 
     SetColor(INFO);
-    y += DrawTextLine(x, y, "Android Recovery", true);
-    std::string recovery_fingerprint =
-        android::base::GetProperty("ro.bootimage.build.fingerprint", "");
-    for (const auto& chunk : android::base::Split(recovery_fingerprint, ":")) {
-      y += DrawTextLine(x, y, chunk, false);
+
+    for (size_t i = 0; i < title_lines_.size(); i++) {
+      y += DrawTextLine(x, y, title_lines_[i], i == 0);
     }
 
     y += DrawTextLines(x, y, help_message);
diff --git a/screen_ui.h b/screen_ui.h
index 2d6b621..c90a2cd 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -141,6 +141,7 @@
   size_t ShowMenu(const std::vector<std::string>& headers, const std::vector<std::string>& items,
                   size_t initial_selection, bool menu_only,
                   const std::function<int(int, bool)>& key_handler) override;
+  void SetTitle(const std::vector<std::string>& lines) override;
 
   void KeyLongPress(int) override;
 
@@ -266,6 +267,8 @@
   bool show_text;
   bool show_text_ever;  // has show_text ever been true?
 
+  std::vector<std::string> title_lines_;
+
   bool scrollable_menu_;
   std::unique_ptr<Menu> menu_;
 
diff --git a/stub_ui.h b/stub_ui.h
index 67c338e..a3cf12b 100644
--- a/stub_ui.h
+++ b/stub_ui.h
@@ -67,6 +67,8 @@
                   const std::function<int(int, bool)>& /* key_handler */) override {
     return initial_selection;
   }
+
+  void SetTitle(const std::vector<std::string>& /* lines */) override {}
 };
 
 #endif  // RECOVERY_STUB_UI_H
diff --git a/tests/Android.mk b/tests/Android.mk
index cdc5b52..efe46b8 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -150,6 +150,18 @@
     libbrotli \
     $(tune2fs_static_libraries)
 
+health_hal_static_libraries := \
+    android.hardware.health@2.0-impl \
+    android.hardware.health@2.0 \
+    android.hardware.health@1.0 \
+    android.hardware.health@1.0-convert \
+    libhealthstoragedefault \
+    libhidltransport \
+    libhidlbase \
+    libhwbinder_noltopgo \
+    libvndksupport \
+    libbatterymonitor
+
 librecovery_static_libraries := \
     librecovery \
     $(TARGET_RECOVERY_UI_LIB) \
@@ -160,8 +172,8 @@
     libminui \
     libverifier \
     libotautil \
+    $(health_hal_static_libraries) \
     libasyncio \
-    libbatterymonitor \
     libcrypto_utils \
     libcrypto \
     libext4_utils \
@@ -174,8 +186,8 @@
     libtinyxml2 \
     libziparchive \
     libbase \
-    libcutils \
     libutils \
+    libcutils \
     liblog \
     libselinux \
     libz \
diff --git a/ui.h b/ui.h
index 3928426..a74b14f 100644
--- a/ui.h
+++ b/ui.h
@@ -134,6 +134,8 @@
 
   // --- menu display ---
 
+  virtual void SetTitle(const std::vector<std::string>& lines) = 0;
+
   // Displays a menu with the given 'headers' and 'items'. The supplied 'key_handler' callback,
   // which is typically bound to Device::HandleMenuKey(), should return the expected action for the
   // given key code and menu visibility (e.g. to move the cursor or to select an item). Caller sets
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 236644e..4a70b98 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -82,7 +82,7 @@
 
 // Parse the last command index of the last update and save the result to |last_command_index|.
 // Return true if we successfully read the index.
-static bool ParseLastCommandFile(int* last_command_index) {
+static bool ParseLastCommandFile(size_t* last_command_index) {
   const std::string& last_command_file = Paths::Get().last_command_file();
   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(last_command_file.c_str(), O_RDONLY)));
   if (fd == -1) {
@@ -133,7 +133,7 @@
 }
 
 // Update the last executed command index in the last_command_file.
-static bool UpdateLastCommandIndex(int command_index, const std::string& command_string) {
+static bool UpdateLastCommandIndex(size_t command_index, const std::string& command_string) {
   const std::string& last_command_file = Paths::Get().last_command_file();
   std::string last_command_tmp = last_command_file + ".tmp";
   std::string content = std::to_string(command_index) + "\n" + command_string;
@@ -546,7 +546,6 @@
 struct CommandParameters {
     std::vector<std::string> tokens;
     size_t cpos;
-    int cmdindex;
     const char* cmdname;
     const char* cmdline;
     std::string freestash;
@@ -1666,7 +1665,6 @@
     return StringValue("t");
   }
 
-  size_t start = 2;
   if (lines.size() < 4) {
     ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
                lines.size());
@@ -1691,8 +1689,8 @@
 
   params.createdstash = res;
 
-  // When performing an update, save the index and cmdline of the current command into
-  // the last_command_file.
+  // When performing an update, save the index and cmdline of the current command into the
+  // last_command_file.
   // Upon resuming an update, read the saved index first; then
   //   1. In verification mode, check if the 'move' or 'diff' commands before the saved index has
   //      the expected target blocks already. If not, these commands cannot be skipped and we need
@@ -1701,15 +1699,14 @@
   //   2. In update mode, skip all commands before the saved index. Therefore, we can avoid deleting
   //      stashes with duplicate id unintentionally (b/69858743); and also speed up the update.
   // If an update succeeds or is unresumable, delete the last_command_file.
-  int saved_last_command_index;
+  bool skip_executed_command = true;
+  size_t saved_last_command_index;
   if (!ParseLastCommandFile(&saved_last_command_index)) {
     DeleteLastCommandFile();
-    // We failed to parse the last command, set it explicitly to -1.
-    saved_last_command_index = -1;
+    // We failed to parse the last command. Disallow skipping executed commands.
+    skip_executed_command = false;
   }
 
-  start += 2;
-
   // Build a map of the available commands
   std::unordered_map<std::string, const Command*> cmd_map;
   for (size_t i = 0; i < cmdcount; ++i) {
@@ -1722,18 +1719,15 @@
 
   int rc = -1;
 
+  static constexpr size_t kTransferListHeaderLines = 4;
   // Subsequent lines are all individual transfer commands
-  for (size_t i = start; i < lines.size(); i++) {
+  for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) {
     const std::string& line = lines[i];
     if (line.empty()) continue;
 
+    size_t cmdindex = i - kTransferListHeaderLines;
     params.tokens = android::base::Split(line, " ");
     params.cpos = 0;
-    if (i - start > std::numeric_limits<int>::max()) {
-      params.cmdindex = -1;
-    } else {
-      params.cmdindex = i - start;
-    }
     params.cmdname = params.tokens[params.cpos++].c_str();
     params.cmdline = line.c_str();
     params.target_verified = false;
@@ -1756,9 +1750,9 @@
 
     // Skip all commands before the saved last command index when resuming an update, except for
     // "new" command. Because new commands read in the data sequentially.
-    if (params.canwrite && params.cmdindex != -1 && params.cmdindex <= saved_last_command_index &&
+    if (params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index &&
         cmdname != "new") {
-      LOG(INFO) << "Skipping already executed command: " << params.cmdindex
+      LOG(INFO) << "Skipping already executed command: " << cmdindex
                 << ", last executed command for previous update: " << saved_last_command_index;
       continue;
     }
@@ -1768,17 +1762,16 @@
       goto pbiudone;
     }
 
-    // In verify mode, check if the commands before the saved last_command_index have been
-    // executed correctly. If some target blocks have unexpected contents, delete the last command
-    // file so that we will resume the update from the first command in the transfer list.
-    if (!params.canwrite && saved_last_command_index != -1 && params.cmdindex != -1 &&
-        params.cmdindex <= saved_last_command_index) {
+    // In verify mode, check if the commands before the saved last_command_index have been executed
+    // correctly. If some target blocks have unexpected contents, delete the last command file so
+    // that we will resume the update from the first command in the transfer list.
+    if (!params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index) {
       // TODO(xunchang) check that the cmdline of the saved index is correct.
       if ((cmdname == "move" || cmdname == "bsdiff" || cmdname == "imgdiff") &&
           !params.target_verified) {
         LOG(WARNING) << "Previously executed command " << saved_last_command_index << ": "
                      << params.cmdline << " doesn't produce expected target blocks.";
-        saved_last_command_index = -1;
+        skip_executed_command = false;
         DeleteLastCommandFile();
       }
     }
@@ -1789,7 +1782,7 @@
         goto pbiudone;
       }
 
-      if (!UpdateLastCommandIndex(params.cmdindex, params.cmdline)) {
+      if (!UpdateLastCommandIndex(cmdindex, params.cmdline)) {
         LOG(WARNING) << "Failed to update the last command file.";
       }
 
diff --git a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
index 222bb0a..ac6e223 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java
@@ -116,6 +116,8 @@
                 PackageFiles.PAYLOAD_PROPERTIES_FILE_NAME
             );
 
+    private final PayloadSpecs mPayloadSpecs = new PayloadSpecs();
+
     @Override
     protected void onHandleIntent(Intent intent) {
         Log.d(TAG, "On handle intent is called");
@@ -137,7 +139,7 @@
      * 3. Checks OTA package compatibility with the device.
      * 4. Constructs {@link PayloadSpec} for streaming update.
      */
-    private static PayloadSpec execute(UpdateConfig config)
+    private PayloadSpec execute(UpdateConfig config)
             throws IOException, PreparationFailedException {
 
         downloadPreStreamingFiles(config, OTA_PACKAGE_DIR);
@@ -164,7 +166,7 @@
             }
         }
 
-        return PayloadSpecs.forStreaming(config.getUrl(),
+        return mPayloadSpecs.forStreaming(config.getUrl(),
                 payloadBinary.get().getOffset(),
                 payloadBinary.get().getSize(),
                 Paths.get(OTA_PACKAGE_DIR, PAYLOAD_PROPERTIES_FILE_NAME).toFile());
@@ -176,7 +178,7 @@
      * in directory {@code dir}.
      * @throws IOException when can't download a file
      */
-    private static void downloadPreStreamingFiles(UpdateConfig config, String dir)
+    private void downloadPreStreamingFiles(UpdateConfig config, String dir)
             throws IOException {
         Log.d(TAG, "Deleting existing files from " + dir);
         for (String file : PRE_STREAMING_FILES_SET) {
@@ -200,7 +202,7 @@
      * @param file physical location of {@link PackageFiles#COMPATIBILITY_ZIP_FILE_NAME}
      * @return true if OTA package is compatible with this device
      */
-    private static boolean verifyPackageCompatibility(File file) {
+    private boolean verifyPackageCompatibility(File file) {
         try {
             return RecoverySystem.verifyPackageCompatibility(file);
         } catch (IOException e) {
diff --git a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java
index c5a7f95..9bab131 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java
@@ -77,6 +77,7 @@
             new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE);
     private PayloadSpec mLastPayloadSpec;
     private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true);
+    private final PayloadSpecs mPayloadSpecs = new PayloadSpecs();
 
     /**
      * Listen to {@code update_engine} events.
@@ -338,7 +339,7 @@
         if (config.getInstallType() == UpdateConfig.AB_INSTALL_TYPE_NON_STREAMING) {
             PayloadSpec payload;
             try {
-                payload = PayloadSpecs.forNonStreaming(config.getUpdatePackageFile());
+                payload = mPayloadSpecs.forNonStreaming(config.getUpdatePackageFile());
             } catch (IOException e) {
                 Log.e(TAG, "Error creating payload spec", e);
                 Toast.makeText(this, "Error creating payload spec", Toast.LENGTH_LONG)
diff --git a/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java b/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java
index 4db448a..b98b97c 100644
--- a/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java
+++ b/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java
@@ -43,7 +43,7 @@
      * zip file. So we enumerate the entries to identify the offset of the payload file.
      * http://developer.android.com/reference/java/util/zip/ZipFile.html#entries()
      */
-    public static PayloadSpec forNonStreaming(File packageFile) throws IOException {
+    public PayloadSpec forNonStreaming(File packageFile) throws IOException {
         boolean payloadFound = false;
         long payloadOffset = 0;
         long payloadSize = 0;
@@ -100,7 +100,7 @@
     /**
      * Creates a {@link PayloadSpec} for streaming update.
      */
-    public static PayloadSpec forStreaming(String updateUrl,
+    public PayloadSpec forStreaming(String updateUrl,
                                            long offset,
                                            long size,
                                            File propertiesFile) throws IOException {
@@ -115,7 +115,7 @@
     /**
      * Converts an {@link PayloadSpec} to a string.
      */
-    public static String toString(PayloadSpec payloadSpec) {
+    public String specToString(PayloadSpec payloadSpec) {
         return "<PayloadSpec url=" + payloadSpec.getUrl()
                 + ", offset=" + payloadSpec.getOffset()
                 + ", size=" + payloadSpec.getSize()
@@ -124,6 +124,4 @@
                 + ">";
     }
 
-    private PayloadSpecs() {}
-
 }
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
index d9e5465..3ba84c1 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
@@ -55,6 +55,8 @@
     private Context mTargetContext;
     private Context mTestContext;
 
+    private PayloadSpecs mPayloadSpecs;
+
     @Rule
     public final ExpectedException thrown = ExpectedException.none();
 
@@ -64,6 +66,7 @@
         mTestContext = InstrumentationRegistry.getContext();
 
         mTestDir = mTargetContext.getFilesDir();
+        mPayloadSpecs = new PayloadSpecs();
     }
 
     @Test
@@ -75,7 +78,7 @@
         java.nio.file.Files.deleteIfExists(packageFile.toPath());
         java.nio.file.Files.copy(mTestContext.getResources().openRawResource(R.raw.ota_002_package),
                 packageFile.toPath());
-        PayloadSpec spec = PayloadSpecs.forNonStreaming(packageFile);
+        PayloadSpec spec = mPayloadSpecs.forNonStreaming(packageFile);
 
         assertEquals("correct url", "file://" + packageFile.getAbsolutePath(), spec.getUrl());
         assertEquals("correct payload offset",
@@ -90,7 +93,7 @@
     @Test
     public void forNonStreaming_IOException() throws Exception {
         thrown.expect(IOException.class);
-        PayloadSpecs.forNonStreaming(new File("/fake/news.zip"));
+        mPayloadSpecs.forNonStreaming(new File("/fake/news.zip"));
     }
 
     @Test
@@ -100,7 +103,7 @@
         long size = 200;
         File propertiesFile = createMockPropertiesFile();
 
-        PayloadSpec spec = PayloadSpecs.forStreaming(url, offset, size, propertiesFile);
+        PayloadSpec spec = mPayloadSpecs.forStreaming(url, offset, size, propertiesFile);
         assertEquals("same url", url, spec.getUrl());
         assertEquals("same offset", offset, spec.getOffset());
         assertEquals("same size", size, spec.getSize());