release-request-38d4765e-6779-4912-a79f-25f77b8184a7-for-git_pi-release-4288638 snap-temp-L71800000095143664

Change-Id: If9aea87ddc40046a6a003fbd4086643ade41eb23
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 7aed0a9..e38207c 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -151,7 +151,8 @@
 LOCAL_STATIC_LIBRARIES := \
     $(libimgdiff_static_libraries)
 LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include
+    $(LOCAL_PATH)/include \
+    bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 include $(BUILD_STATIC_LIBRARY)
 
@@ -166,7 +167,8 @@
 LOCAL_STATIC_LIBRARIES := \
     $(libimgdiff_static_libraries)
 LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include
+    $(LOCAL_PATH)/include \
+    bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 include $(BUILD_HOST_STATIC_LIBRARY)
 
@@ -180,4 +182,7 @@
     libimgdiff \
     $(libimgdiff_static_libraries) \
     libbz
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/include \
+    bootable/recovery
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index a81e385..59b6007 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -140,11 +140,12 @@
 #include <android-base/logging.h>
 #include <android-base/memory.h>
 #include <android-base/unique_fd.h>
-#include <ziparchive/zip_archive.h>
-
 #include <bsdiff.h>
+#include <ziparchive/zip_archive.h>
 #include <zlib.h>
 
+#include "applypatch/imgdiff_image.h"
+
 using android::base::get_unaligned;
 
 static constexpr auto BUFFER_SIZE = 0x8000;
@@ -161,99 +162,16 @@
   return android::base::WriteFully(fd, &value, sizeof(int32_t));
 }
 
-class ImageChunk {
- public:
-  static constexpr auto WINDOWBITS = -15;  // 32kb window; negative to indicate a raw stream.
-  static constexpr auto MEMLEVEL = 8;      // the default value.
-  static constexpr auto METHOD = Z_DEFLATED;
-  static constexpr auto STRATEGY = Z_DEFAULT_STRATEGY;
-
-  ImageChunk(int type, size_t start, const std::vector<uint8_t>* file_content, size_t raw_data_len,
-             std::string entry_name = {})
-      : type_(type),
-        start_(start),
-        input_file_ptr_(file_content),
-        raw_data_len_(raw_data_len),
-        compress_level_(6),
-        entry_name_(std::move(entry_name)) {
-    CHECK(file_content != nullptr) << "input file container can't be nullptr";
-  }
-
-  int GetType() const {
-    return type_;
-  }
-  size_t GetRawDataLength() const {
-    return raw_data_len_;
-  }
-  const std::string& GetEntryName() const {
-    return entry_name_;
-  }
-  size_t GetStartOffset() const {
-    return start_;
-  }
-  int GetCompressLevel() const {
-    return compress_level_;
-  }
-
-  // CHUNK_DEFLATE will return the uncompressed data for diff, while other types will simply return
-  // the raw data.
-  const uint8_t * DataForPatch() const;
-  size_t DataLengthForPatch() const;
-
-  void Dump() const {
-    printf("type: %d, start: %zu, len: %zu, name: %s\n", type_, start_, DataLengthForPatch(),
-           entry_name_.c_str());
-  }
-
-  void SetUncompressedData(std::vector<uint8_t> data);
-  bool SetBonusData(const std::vector<uint8_t>& bonus_data);
-
-  bool operator==(const ImageChunk& other) const;
-  bool operator!=(const ImageChunk& other) const {
-    return !(*this == other);
-  }
-
-  /*
-   * Cause a gzip chunk to be treated as a normal chunk (ie, as a blob of uninterpreted data).
-   * The resulting patch will likely be about as big as the target file, but it lets us handle
-   * the case of images where some gzip chunks are reconstructible but others aren't (by treating
-   * the ones that aren't as normal chunks).
-   */
-  void ChangeDeflateChunkToNormal();
-
-  /*
-   * Verify that we can reproduce exactly the same compressed data that we started with.  Sets the
-   * level, method, windowBits, memLevel, and strategy fields in the chunk to the encoding
-   * parameters needed to produce the right output.
-   */
-  bool ReconstructDeflateChunk();
-  bool IsAdjacentNormal(const ImageChunk& other) const;
-  void MergeAdjacentNormal(const ImageChunk& other);
-
-  /*
-   * Compute a bsdiff patch between |src| and |tgt|; Store the result in the patch_data.
-   * |bsdiff_cache| can be used to cache the suffix array if the same |src| chunk is used
-   * repeatedly, pass nullptr if not needed.
-   */
-  static bool MakePatch(const ImageChunk& tgt, const ImageChunk& src,
-                        std::vector<uint8_t>* patch_data, saidx_t** bsdiff_cache);
-
- private:
-  const uint8_t* GetRawData() const;
-  bool TryReconstruction(int level);
-
-  int type_;                                    // CHUNK_NORMAL, CHUNK_DEFLATE, CHUNK_RAW
-  size_t start_;                                // offset of chunk in the original input file
-  const std::vector<uint8_t>* input_file_ptr_;  // ptr to the full content of original input file
-  size_t raw_data_len_;
-
-  // deflate encoder parameters
-  int compress_level_;
-
-  // --- for CHUNK_DEFLATE chunks only: ---
-  std::vector<uint8_t> uncompressed_data_;
-  std::string entry_name_;  // used for zip entries
-};
+ImageChunk::ImageChunk(int type, size_t start, const std::vector<uint8_t>* file_content,
+                       size_t raw_data_len, std::string entry_name)
+    : type_(type),
+      start_(start),
+      input_file_ptr_(file_content),
+      raw_data_len_(raw_data_len),
+      compress_level_(6),
+      entry_name_(std::move(entry_name)) {
+  CHECK(file_content != nullptr) << "input file container can't be nullptr";
+}
 
 const uint8_t* ImageChunk::GetRawData() const {
   CHECK_LE(start_ + raw_data_len_, input_file_ptr_->size());
@@ -424,57 +342,28 @@
   return true;
 }
 
-// PatchChunk stores the patch data between a source chunk and a target chunk. It also keeps track
-// of the metadata of src&tgt chunks (e.g. offset, raw data length, uncompressed data length).
-class PatchChunk {
- public:
-  PatchChunk(const ImageChunk& tgt, const ImageChunk& src, std::vector<uint8_t> data)
-      : type_(tgt.GetType()),
-        source_start_(src.GetStartOffset()),
-        source_len_(src.GetRawDataLength()),
-        source_uncompressed_len_(src.DataLengthForPatch()),
-        target_start_(tgt.GetStartOffset()),
-        target_len_(tgt.GetRawDataLength()),
-        target_uncompressed_len_(tgt.DataLengthForPatch()),
-        target_compress_level_(tgt.GetCompressLevel()),
-        data_(std::move(data)) {}
+PatchChunk::PatchChunk(const ImageChunk& tgt, const ImageChunk& src, std::vector<uint8_t> data)
+    : type_(tgt.GetType()),
+      source_start_(src.GetStartOffset()),
+      source_len_(src.GetRawDataLength()),
+      source_uncompressed_len_(src.DataLengthForPatch()),
+      target_start_(tgt.GetStartOffset()),
+      target_len_(tgt.GetRawDataLength()),
+      target_uncompressed_len_(tgt.DataLengthForPatch()),
+      target_compress_level_(tgt.GetCompressLevel()),
+      data_(std::move(data)) {}
 
-  // Construct a CHUNK_RAW patch from the target data directly.
-  explicit PatchChunk(const ImageChunk& tgt)
-      : type_(CHUNK_RAW),
-        source_start_(0),
-        source_len_(0),
-        source_uncompressed_len_(0),
-        target_start_(tgt.GetStartOffset()),
-        target_len_(tgt.GetRawDataLength()),
-        target_uncompressed_len_(tgt.DataLengthForPatch()),
-        target_compress_level_(tgt.GetCompressLevel()),
-        data_(tgt.DataForPatch(), tgt.DataForPatch() + tgt.DataLengthForPatch()) {}
-
-  // Return true if raw data size is smaller than the patch size.
-  static bool RawDataIsSmaller(const ImageChunk& tgt, size_t patch_size);
-
-  static bool WritePatchDataToFd(const std::vector<PatchChunk>& patch_chunks, int patch_fd);
-
- private:
-  size_t GetHeaderSize() const;
-  size_t WriteHeaderToFd(int fd, size_t offset) const;
-
-  // The patch chunk type is the same as the target chunk type. The only exception is we change
-  // the |type_| to CHUNK_RAW if target length is smaller than the patch size.
-  int type_;
-
-  size_t source_start_;
-  size_t source_len_;
-  size_t source_uncompressed_len_;
-
-  size_t target_start_;  // offset of the target chunk within the target file
-  size_t target_len_;
-  size_t target_uncompressed_len_;
-  size_t target_compress_level_;  // the deflate compression level of the target chunk.
-
-  std::vector<uint8_t> data_;  // storage for the patch data
-};
+// Construct a CHUNK_RAW patch from the target data directly.
+PatchChunk::PatchChunk(const ImageChunk& tgt)
+    : type_(CHUNK_RAW),
+      source_start_(0),
+      source_len_(0),
+      source_uncompressed_len_(0),
+      target_start_(tgt.GetStartOffset()),
+      target_len_(tgt.GetRawDataLength()),
+      target_uncompressed_len_(tgt.DataLengthForPatch()),
+      target_compress_level_(tgt.GetCompressLevel()),
+      data_(tgt.DataForPatch(), tgt.DataForPatch() + tgt.DataLengthForPatch()) {}
 
 // Return true if raw data is smaller than the patch size.
 bool PatchChunk::RawDataIsSmaller(const ImageChunk& tgt, size_t patch_size) {
@@ -574,59 +463,15 @@
   return true;
 }
 
-// Interface for zip_mode and image_mode images. We initialize the image from an input file and
-// split the file content into a list of image chunks.
-class Image {
- public:
-  explicit Image(bool is_source) : is_source_(is_source) {}
+ImageChunk& Image::operator[](size_t i) {
+  CHECK_LT(i, chunks_.size());
+  return chunks_[i];
+}
 
-  virtual ~Image() {}
-
-  // Create a list of image chunks from input file.
-  virtual bool Initialize(const std::string& filename) = 0;
-
-  // Look for runs of adjacent normal chunks and compress them down into a single chunk.  (Such
-  // runs can be produced when deflate chunks are changed to normal chunks.)
-  void MergeAdjacentNormalChunks();
-
-  // In zip mode, find the matching deflate source chunk by entry name. Search for normal chunks
-  // also if |find_normal| is true.
-  ImageChunk* FindChunkByName(const std::string& name, bool find_normal = false);
-
-  const ImageChunk* FindChunkByName(const std::string& name, bool find_normal = false) const;
-
-  void DumpChunks() const;
-
-  // Non const iterators to access the stored ImageChunks.
-  std::vector<ImageChunk>::iterator begin() {
-    return chunks_.begin();
-  }
-
-  std::vector<ImageChunk>::iterator end() {
-    return chunks_.end();
-  }
-
-  ImageChunk& operator[](size_t i) {
-    CHECK_LT(i, chunks_.size());
-    return chunks_[i];
-  }
-
-  const ImageChunk& operator[](size_t i) const {
-    CHECK_LT(i, chunks_.size());
-    return chunks_[i];
-  }
-
-  size_t NumOfChunks() const {
-    return chunks_.size();
-  }
-
- protected:
-  bool ReadFile(const std::string& filename, std::vector<uint8_t>* file_content);
-
-  bool is_source_;                     // True if it's for source chunks.
-  std::vector<ImageChunk> chunks_;     // Internal storage of ImageChunk.
-  std::vector<uint8_t> file_content_;  // Store the whole input file in memory.
-};
+const ImageChunk& Image::operator[](size_t i) const {
+  CHECK_LT(i, chunks_.size());
+  return chunks_[i];
+}
 
 void Image::MergeAdjacentNormalChunks() {
   size_t merged_last = 0, cur = 0;
@@ -650,23 +495,6 @@
   }
 }
 
-const ImageChunk* Image::FindChunkByName(const std::string& name, bool find_normal) const {
-  if (name.empty()) {
-    return nullptr;
-  }
-  for (auto& chunk : chunks_) {
-    if ((chunk.GetType() == CHUNK_DEFLATE || find_normal) && chunk.GetEntryName() == name) {
-      return &chunk;
-    }
-  }
-  return nullptr;
-}
-
-ImageChunk* Image::FindChunkByName(const std::string& name, bool find_normal) {
-  return const_cast<ImageChunk*>(
-      static_cast<const Image*>(this)->FindChunkByName(name, find_normal));
-}
-
 void Image::DumpChunks() const {
   std::string type = is_source_ ? "source" : "target";
   printf("Dumping chunks for %s\n", type.c_str());
@@ -701,39 +529,6 @@
   return true;
 }
 
-class ZipModeImage : public Image {
- public:
-  explicit ZipModeImage(bool is_source) : Image(is_source) {}
-
-  bool Initialize(const std::string& filename) override;
-
-  const ImageChunk& PseudoSource() const {
-    CHECK(is_source_);
-    CHECK(pseudo_source_ != nullptr);
-    return *pseudo_source_;
-  }
-
-  // Verify that we can reconstruct the deflate chunks; also change the type to CHUNK_NORMAL if
-  // src and tgt are identical.
-  static bool CheckAndProcessChunks(ZipModeImage* tgt_image, ZipModeImage* src_image);
-
-  // Compute the patch between tgt & src images, and write the data into |patch_name|.
-  static bool GeneratePatches(const ZipModeImage& tgt_image, const ZipModeImage& src_image,
-                              const std::string& patch_name);
-
- private:
-  // Initialize image chunks based on the zip entries.
-  bool InitializeChunks(const std::string& filename, ZipArchiveHandle handle);
-  // Add the a zip entry to the list.
-  bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, ZipEntry* entry);
-  // Return the real size of the zip file. (omit the trailing zeros that used for alignment)
-  bool GetZipFileSize(size_t* input_file_size);
-
-  // The pesudo source chunk for bsdiff if there's no match for the given target chunk. It's in
-  // fact the whole source file.
-  std::unique_ptr<ImageChunk> pseudo_source_;
-};
-
 bool ZipModeImage::Initialize(const std::string& filename) {
   if (!ReadFile(filename, &file_content_)) {
     return false;
@@ -754,9 +549,6 @@
     return false;
   }
 
-  if (is_source_) {
-    pseudo_source_ = std::make_unique<ImageChunk>(CHUNK_NORMAL, 0, &file_content_, zipfile_size);
-  }
   if (!InitializeChunks(filename, handle)) {
     CloseArchive(handle);
     return false;
@@ -895,6 +687,28 @@
   return false;
 }
 
+ImageChunk ZipModeImage::PseudoSource() const {
+  CHECK(is_source_);
+  return ImageChunk(CHUNK_NORMAL, 0, &file_content_, file_content_.size());
+}
+
+const ImageChunk* ZipModeImage::FindChunkByName(const std::string& name, bool find_normal) const {
+  if (name.empty()) {
+    return nullptr;
+  }
+  for (auto& chunk : chunks_) {
+    if ((chunk.GetType() == CHUNK_DEFLATE || find_normal) && chunk.GetEntryName() == name) {
+      return &chunk;
+    }
+  }
+  return nullptr;
+}
+
+ImageChunk* ZipModeImage::FindChunkByName(const std::string& name, bool find_normal) {
+  return const_cast<ImageChunk*>(
+      static_cast<const ZipModeImage*>(this)->FindChunkByName(name, find_normal));
+}
+
 bool ZipModeImage::CheckAndProcessChunks(ZipModeImage* tgt_image, ZipModeImage* src_image) {
   for (auto& tgt_chunk : *tgt_image) {
     if (tgt_chunk.GetType() != CHUNK_DEFLATE) {
@@ -981,25 +795,6 @@
   return PatchChunk::WritePatchDataToFd(patch_chunks, patch_fd);
 }
 
-class ImageModeImage : public Image {
- public:
-  explicit ImageModeImage(bool is_source) : Image(is_source) {}
-
-  // Initialize the image chunks list by searching the magic numbers in an image file.
-  bool Initialize(const std::string& filename) override;
-
-  bool SetBonusData(const std::vector<uint8_t>& bonus_data);
-
-  // In Image Mode, verify that the source and target images have the same chunk structure (ie, the
-  // same sequence of deflate and normal chunks).
-  static bool CheckAndProcessChunks(ImageModeImage* tgt_image, ImageModeImage* src_image);
-
-  // In image mode, generate patches against the given source chunks and bonus_data; write the
-  // result to |patch_name|.
-  static bool GeneratePatches(const ImageModeImage& tgt_image, const ImageModeImage& src_image,
-                              const std::string& patch_name);
-};
-
 bool ImageModeImage::Initialize(const std::string& filename) {
   if (!ReadFile(filename, &file_content_)) {
     return false;
diff --git a/applypatch/include/applypatch/imgdiff_image.h b/applypatch/include/applypatch/imgdiff_image.h
new file mode 100644
index 0000000..221dd5a
--- /dev/null
+++ b/applypatch/include/applypatch/imgdiff_image.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _APPLYPATCH_IMGDIFF_IMAGE_H
+#define _APPLYPATCH_IMGDIFF_IMAGE_H
+
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+#include <bsdiff.h>
+#include <ziparchive/zip_archive.h>
+#include <zlib.h>
+
+#include "imgdiff.h"
+#include "rangeset.h"
+
+class ImageChunk {
+ public:
+  static constexpr auto WINDOWBITS = -15;  // 32kb window; negative to indicate a raw stream.
+  static constexpr auto MEMLEVEL = 8;      // the default value.
+  static constexpr auto METHOD = Z_DEFLATED;
+  static constexpr auto STRATEGY = Z_DEFAULT_STRATEGY;
+
+  ImageChunk(int type, size_t start, const std::vector<uint8_t>* file_content, size_t raw_data_len,
+             std::string entry_name = {});
+
+  int GetType() const {
+    return type_;
+  }
+  size_t GetRawDataLength() const {
+    return raw_data_len_;
+  }
+  const std::string& GetEntryName() const {
+    return entry_name_;
+  }
+  size_t GetStartOffset() const {
+    return start_;
+  }
+  int GetCompressLevel() const {
+    return compress_level_;
+  }
+
+  // CHUNK_DEFLATE will return the uncompressed data for diff, while other types will simply return
+  // the raw data.
+  const uint8_t* DataForPatch() const;
+  size_t DataLengthForPatch() const;
+
+  void Dump() const {
+    printf("type: %d, start: %zu, len: %zu, name: %s\n", type_, start_, DataLengthForPatch(),
+           entry_name_.c_str());
+  }
+
+  void SetUncompressedData(std::vector<uint8_t> data);
+  bool SetBonusData(const std::vector<uint8_t>& bonus_data);
+
+  bool operator==(const ImageChunk& other) const;
+  bool operator!=(const ImageChunk& other) const {
+    return !(*this == other);
+  }
+
+  /*
+   * Cause a gzip chunk to be treated as a normal chunk (ie, as a blob of uninterpreted data).
+   * The resulting patch will likely be about as big as the target file, but it lets us handle
+   * the case of images where some gzip chunks are reconstructible but others aren't (by treating
+   * the ones that aren't as normal chunks).
+   */
+  void ChangeDeflateChunkToNormal();
+
+  /*
+   * Verify that we can reproduce exactly the same compressed data that we started with.  Sets the
+   * level, method, windowBits, memLevel, and strategy fields in the chunk to the encoding
+   * parameters needed to produce the right output.
+   */
+  bool ReconstructDeflateChunk();
+  bool IsAdjacentNormal(const ImageChunk& other) const;
+  void MergeAdjacentNormal(const ImageChunk& other);
+
+  /*
+   * Compute a bsdiff patch between |src| and |tgt|; Store the result in the patch_data.
+   * |bsdiff_cache| can be used to cache the suffix array if the same |src| chunk is used
+   * repeatedly, pass nullptr if not needed.
+   */
+  static bool MakePatch(const ImageChunk& tgt, const ImageChunk& src,
+                        std::vector<uint8_t>* patch_data, saidx_t** bsdiff_cache);
+
+ private:
+  const uint8_t* GetRawData() const;
+  bool TryReconstruction(int level);
+
+  int type_;                                    // CHUNK_NORMAL, CHUNK_DEFLATE, CHUNK_RAW
+  size_t start_;                                // offset of chunk in the original input file
+  const std::vector<uint8_t>* input_file_ptr_;  // ptr to the full content of original input file
+  size_t raw_data_len_;
+
+  // deflate encoder parameters
+  int compress_level_;
+
+  // --- for CHUNK_DEFLATE chunks only: ---
+  std::vector<uint8_t> uncompressed_data_;
+  std::string entry_name_;  // used for zip entries
+};
+
+// PatchChunk stores the patch data between a source chunk and a target chunk. It also keeps track
+// of the metadata of src&tgt chunks (e.g. offset, raw data length, uncompressed data length).
+class PatchChunk {
+ public:
+  PatchChunk(const ImageChunk& tgt, const ImageChunk& src, std::vector<uint8_t> data);
+
+  // Construct a CHUNK_RAW patch from the target data directly.
+  explicit PatchChunk(const ImageChunk& tgt);
+
+  // Return true if raw data size is smaller than the patch size.
+  static bool RawDataIsSmaller(const ImageChunk& tgt, size_t patch_size);
+
+  static bool WritePatchDataToFd(const std::vector<PatchChunk>& patch_chunks, int patch_fd);
+
+ private:
+  size_t GetHeaderSize() const;
+  size_t WriteHeaderToFd(int fd, size_t offset) const;
+
+  // The patch chunk type is the same as the target chunk type. The only exception is we change
+  // the |type_| to CHUNK_RAW if target length is smaller than the patch size.
+  int type_;
+
+  size_t source_start_;
+  size_t source_len_;
+  size_t source_uncompressed_len_;
+
+  size_t target_start_;  // offset of the target chunk within the target file
+  size_t target_len_;
+  size_t target_uncompressed_len_;
+  size_t target_compress_level_;  // the deflate compression level of the target chunk.
+
+  std::vector<uint8_t> data_;  // storage for the patch data
+};
+
+// Interface for zip_mode and image_mode images. We initialize the image from an input file and
+// split the file content into a list of image chunks.
+class Image {
+ public:
+  explicit Image(bool is_source) : is_source_(is_source) {}
+
+  virtual ~Image() {}
+
+  // Create a list of image chunks from input file.
+  virtual bool Initialize(const std::string& filename) = 0;
+
+  // Look for runs of adjacent normal chunks and compress them down into a single chunk.  (Such
+  // runs can be produced when deflate chunks are changed to normal chunks.)
+  void MergeAdjacentNormalChunks();
+
+  void DumpChunks() const;
+
+  // Non const iterators to access the stored ImageChunks.
+  std::vector<ImageChunk>::iterator begin() {
+    return chunks_.begin();
+  }
+
+  std::vector<ImageChunk>::iterator end() {
+    return chunks_.end();
+  }
+
+  ImageChunk& operator[](size_t i);
+  const ImageChunk& operator[](size_t i) const;
+
+  size_t NumOfChunks() const {
+    return chunks_.size();
+  }
+
+ protected:
+  bool ReadFile(const std::string& filename, std::vector<uint8_t>* file_content);
+
+  bool is_source_;                     // True if it's for source chunks.
+  std::vector<ImageChunk> chunks_;     // Internal storage of ImageChunk.
+  std::vector<uint8_t> file_content_;  // Store the whole input file in memory.
+};
+
+class ZipModeImage : public Image {
+ public:
+  explicit ZipModeImage(bool is_source) : Image(is_source) {}
+
+  bool Initialize(const std::string& filename) override;
+
+  // The pesudo source chunk for bsdiff if there's no match for the given target chunk. It's in
+  // fact the whole source file.
+  ImageChunk PseudoSource() const;
+
+  // Find the matching deflate source chunk by entry name. Search for normal chunks also if
+  // |find_normal| is true.
+  ImageChunk* FindChunkByName(const std::string& name, bool find_normal = false);
+
+  const ImageChunk* FindChunkByName(const std::string& name, bool find_normal = false) const;
+
+  // Verify that we can reconstruct the deflate chunks; also change the type to CHUNK_NORMAL if
+  // src and tgt are identical.
+  static bool CheckAndProcessChunks(ZipModeImage* tgt_image, ZipModeImage* src_image);
+
+  // Compute the patch between tgt & src images, and write the data into |patch_name|.
+  static bool GeneratePatches(const ZipModeImage& tgt_image, const ZipModeImage& src_image,
+                              const std::string& patch_name);
+
+ private:
+  // Initialize image chunks based on the zip entries.
+  bool InitializeChunks(const std::string& filename, ZipArchiveHandle handle);
+  // Add the a zip entry to the list.
+  bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, ZipEntry* entry);
+  // Return the real size of the zip file. (omit the trailing zeros that used for alignment)
+  bool GetZipFileSize(size_t* input_file_size);
+};
+
+class ImageModeImage : public Image {
+ public:
+  explicit ImageModeImage(bool is_source) : Image(is_source) {}
+
+  // Initialize the image chunks list by searching the magic numbers in an image file.
+  bool Initialize(const std::string& filename) override;
+
+  bool SetBonusData(const std::vector<uint8_t>& bonus_data);
+
+  // In Image Mode, verify that the source and target images have the same chunk structure (ie, the
+  // same sequence of deflate and normal chunks).
+  static bool CheckAndProcessChunks(ImageModeImage* tgt_image, ImageModeImage* src_image);
+
+  // In image mode, generate patches against the given source chunks and bonus_data; write the
+  // result to |patch_name|.
+  static bool GeneratePatches(const ImageModeImage& tgt_image, const ImageModeImage& src_image,
+                              const std::string& patch_name);
+};
+
+#endif  // _APPLYPATCH_IMGDIFF_IMAGE_H
diff --git a/updater/include/updater/rangeset.h b/rangeset.h
similarity index 96%
rename from updater/include/updater/rangeset.h
rename to rangeset.h
index b67c987..f224a08 100644
--- a/updater/include/updater/rangeset.h
+++ b/rangeset.h
@@ -266,13 +266,13 @@
         new_block_start += (old_block_start - range.first);
         return (new_block_start * kBlockSize + old_offset % kBlockSize);
       } else {
-        CHECK(false) <<"block_start " << old_block_start << " is missing between two ranges: "
-                     << this->ToString();
+        CHECK(false) << "block_start " << old_block_start
+                     << " is missing between two ranges: " << this->ToString();
         return 0;
       }
     }
-    CHECK(false) <<"block_start " << old_block_start << " exceeds the limit of current RangeSet: "
-                 << this->ToString();
+    CHECK(false) << "block_start " << old_block_start
+                 << " exceeds the limit of current RangeSet: " << this->ToString();
     return 0;
   }
 };
\ No newline at end of file
diff --git a/screen_ui.cpp b/screen_ui.cpp
index e056512..a025501 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -344,7 +344,8 @@
     y += DrawTextLines(x, y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
 
     SetColor(HEADER);
-    y += DrawWrappedTextLines(x, y, menu_headers_);
+    // Ignore kMenuIndent, which is not taken into account by text_cols_.
+    y += DrawWrappedTextLines(kMarginWidth, y, menu_headers_);
 
     SetColor(MENU);
     y += DrawHorizontalRule(y) + 4;
diff --git a/tests/unit/rangeset_test.cpp b/tests/unit/rangeset_test.cpp
index 3993cb9..15bcec8 100644
--- a/tests/unit/rangeset_test.cpp
+++ b/tests/unit/rangeset_test.cpp
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include "updater/rangeset.h"
+#include "rangeset.h"
 
 TEST(RangeSetTest, Parse_smoke) {
   RangeSet rs = RangeSet::Parse("2,1,10");
diff --git a/tools/recovery_l10n/res/values-az/strings.xml b/tools/recovery_l10n/res/values-az/strings.xml
new file mode 100644
index 0000000..c6765a9
--- /dev/null
+++ b/tools/recovery_l10n/res/values-az/strings.xml
@@ -0,0 +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">"Sistem güncəlləməsi quraşdırılır..."</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Silinir"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"Əmr yoxdur"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Xəta!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Təhlükəsizlik güncəlləməsi yüklənir"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..c2d8f22
--- /dev/null
+++ b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"Greška!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Instalira se bezbednosno ažuriranje"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-be/strings.xml b/tools/recovery_l10n/res/values-be/strings.xml
new file mode 100644
index 0000000..7c0954d
--- /dev/null
+++ b/tools/recovery_l10n/res/values-be/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"Памылка"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Усталёўка абнаўлення сістэмы бяспекі"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-bs/strings.xml b/tools/recovery_l10n/res/values-bs/strings.xml
new file mode 100644
index 0000000..412cf02
--- /dev/null
+++ b/tools/recovery_l10n/res/values-bs/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"Greška!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Instaliranje sigurnosnog ažuriranja…"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-en-rAU/strings.xml b/tools/recovery_l10n/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..dc75c23
--- /dev/null
+++ b/tools/recovery_l10n/res/values-en-rAU/strings.xml
@@ -0,0 +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">"Installing system update"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Error!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-en-rCA/strings.xml b/tools/recovery_l10n/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..dc75c23
--- /dev/null
+++ b/tools/recovery_l10n/res/values-en-rCA/strings.xml
@@ -0,0 +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">"Installing system update"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Error!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-en-rXC/strings.xml b/tools/recovery_l10n/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..2d528b3
--- /dev/null
+++ b/tools/recovery_l10n/res/values-en-rXC/strings.xml
@@ -0,0 +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">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎Installing system update‎‏‎‎‏‎"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎Erasing‎‏‎‎‏‎"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎No command‎‏‎‎‏‎"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎Error!‎‏‎‎‏‎"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎Installing security update‎‏‎‎‏‎"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-gu/strings.xml b/tools/recovery_l10n/res/values-gu/strings.xml
new file mode 100644
index 0000000..2355a0f
--- /dev/null
+++ b/tools/recovery_l10n/res/values-gu/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"ભૂલ!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"સુરક્ષા અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-kk/strings.xml b/tools/recovery_l10n/res/values-kk/strings.xml
new file mode 100644
index 0000000..a4bd86e
--- /dev/null
+++ b/tools/recovery_l10n/res/values-kk/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"Қате!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Қауіпсіздік жаңартуы орнатылуда"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-kn/strings.xml b/tools/recovery_l10n/res/values-kn/strings.xml
new file mode 100644
index 0000000..5bf6260
--- /dev/null
+++ b/tools/recovery_l10n/res/values-kn/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"ದೋಷ!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"ಭದ್ರತೆಯ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-pa/strings.xml b/tools/recovery_l10n/res/values-pa/strings.xml
new file mode 100644
index 0000000..8564c9c
--- /dev/null
+++ b/tools/recovery_l10n/res/values-pa/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"ਅਸ਼ੁੱਧੀ!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-pt-rBR/strings.xml b/tools/recovery_l10n/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..b727043
--- /dev/null
+++ b/tools/recovery_l10n/res/values-pt-rBR/strings.xml
@@ -0,0 +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">"Instalando atualização do sistema"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Apagando"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"Nenhum comando"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Erro!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Instalando atualização de segurança"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-sq/strings.xml b/tools/recovery_l10n/res/values-sq/strings.xml
new file mode 100644
index 0000000..1156931
--- /dev/null
+++ b/tools/recovery_l10n/res/values-sq/strings.xml
@@ -0,0 +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">"Po instalon përditësimin e sistemit"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Po spastron"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"Nuk ka komanda"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Gabim!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Po instalon përditësimin e sigurisë"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml
new file mode 100644
index 0000000..cfb02c9
--- /dev/null
+++ b/tools/recovery_l10n/res/values-te/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"లోపం సంభవించింది!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"భద్రతా నవీకరణను ఇన్‌స్టాల్ చేస్తోంది"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-ur/strings.xml b/tools/recovery_l10n/res/values-ur/strings.xml
new file mode 100644
index 0000000..12e32fb
--- /dev/null
+++ b/tools/recovery_l10n/res/values-ur/strings.xml
@@ -0,0 +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_error" msgid="5748178989622716736">"خرابی!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"سیکیورٹی اپ ڈیٹ انسٹال ہو رہی ہے"</string>
+</resources>
diff --git a/tools/recovery_l10n/res/values-uz/strings.xml b/tools/recovery_l10n/res/values-uz/strings.xml
new file mode 100644
index 0000000..2c309d6
--- /dev/null
+++ b/tools/recovery_l10n/res/values-uz/strings.xml
@@ -0,0 +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">"Tizim yangilanishi o‘rnatilmoqda"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Tozalanmoqda…"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"Buyruq yo‘q"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"Xato!"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Xavfsizlik yangilanishi o‘rnatilmoqda"</string>
+</resources>
diff --git a/update_verifier/update_verifier_main.cpp b/update_verifier/update_verifier_main.cpp
index 46e8bbb..9dd5a0c 100644
--- a/update_verifier/update_verifier_main.cpp
+++ b/update_verifier/update_verifier_main.cpp
@@ -16,8 +16,14 @@
 
 // See the comments in update_verifier.cpp.
 
+#include <android-base/logging.h>
+
 #include "update_verifier/update_verifier.h"
 
 int main(int argc, char** argv) {
+  // Set up update_verifier logging to be written to kmsg; because we may not have Logd during
+  // boot time.
+  android::base::InitLogging(argv, &android::base::KernelLogger);
+
   return update_verifier(argc, argv);
 }
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index a0b9ad2..fe21dd0 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -53,8 +53,8 @@
 #include "error_code.h"
 #include "ota_io.h"
 #include "print_sha1.h"
+#include "rangeset.h"
 #include "updater/install.h"
-#include "updater/rangeset.h"
 #include "updater/updater.h"
 
 // Set this to 0 to interpret 'erase' transfers to mean do a