Merge "Recovery image is self-contained"
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index c1aab41..cc02e9e 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -28,7 +28,7 @@
 #include "graphics_fbdev.h"
 #include "minui/minui.h"
 
-static GRFont* gr_font = NULL;
+static GRFont* gr_font = nullptr;
 static MinuiBackend* gr_backend = nullptr;
 
 static int overscan_percent = OVERSCAN_PERCENT;
@@ -38,7 +38,8 @@
 static uint32_t gr_current = ~0;
 static constexpr uint32_t alpha_mask = 0xff000000;
 
-static GRSurface* gr_draw = NULL;
+// gr_draw is owned by backends.
+static const GRSurface* gr_draw = nullptr;
 static GRRotation rotation = ROTATION_NONE;
 
 static bool outside(int x, int y) {
@@ -86,7 +87,7 @@
   return (out_r & 0xff) | (out_g & 0xff00) | (out_b & 0xff0000) | (gr_current & 0xff000000);
 }
 
-// increments pixel pointer right, with current rotation.
+// Increments pixel pointer right, with current rotation.
 static void incr_x(uint32_t** p, int row_pixels) {
   if (rotation % 2) {
     *p = *p + (rotation == 1 ? 1 : -1) * row_pixels;
@@ -95,7 +96,7 @@
   }
 }
 
-// increments pixel pointer down, with current rotation.
+// Increments pixel pointer down, with current rotation.
 static void incr_y(uint32_t** p, int row_pixels) {
   if (rotation % 2) {
     *p = *p + (rotation == 1 ? -1 : 1);
@@ -104,8 +105,8 @@
   }
 }
 
-// returns pixel pointer at given coordinates with rotation adjustment.
-static uint32_t* pixel_at(GRSurface* surf, int x, int y, int row_pixels) {
+// Returns pixel pointer at given coordinates with rotation adjustment.
+static uint32_t* pixel_at(const GRSurface* surf, int x, int y, int row_pixels) {
   switch (rotation) {
     case ROTATION_NONE:
       return reinterpret_cast<uint32_t*>(surf->data) + y * row_pixels + x;
@@ -172,7 +173,7 @@
 }
 
 void gr_texticon(int x, int y, GRSurface* icon) {
-  if (icon == NULL) return;
+  if (icon == nullptr) return;
 
   if (icon->pixel_bytes != 1) {
     printf("gr_texticon: source has wrong format\n");
@@ -243,7 +244,7 @@
 }
 
 void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
-  if (source == NULL) return;
+  if (source == nullptr) return;
 
   if (gr_draw->pixel_bytes != source->pixel_bytes) {
     printf("gr_blit: source has wrong format\n");
@@ -275,8 +276,7 @@
     unsigned char* src_p = source->data + sy * source->row_bytes + sx * source->pixel_bytes;
     unsigned char* dst_p = gr_draw->data + dy * gr_draw->row_bytes + dx * gr_draw->pixel_bytes;
 
-    int i;
-    for (i = 0; i < h; ++i) {
+    for (int i = 0; i < h; ++i) {
       memcpy(dst_p, src_p, w * source->pixel_bytes);
       src_p += source->row_bytes;
       dst_p += gr_draw->row_bytes;
@@ -284,15 +284,15 @@
   }
 }
 
-unsigned int gr_get_width(GRSurface* surface) {
-  if (surface == NULL) {
+unsigned int gr_get_width(const GRSurface* surface) {
+  if (surface == nullptr) {
     return 0;
   }
   return surface->width;
 }
 
-unsigned int gr_get_height(GRSurface* surface) {
-  if (surface == NULL) {
+unsigned int gr_get_height(const GRSurface* surface) {
+  if (surface == nullptr) {
     return 0;
   }
   return surface->height;
@@ -372,6 +372,10 @@
 
 void gr_exit() {
   delete gr_backend;
+  gr_backend = nullptr;
+
+  delete gr_font;
+  gr_font = nullptr;
 }
 
 int gr_fb_width() {
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index e96b7ae..ef4abe2 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -48,7 +48,13 @@
   ROTATION_LEFT = 3,
 };
 
+// Initializes the graphics backend and loads font file. Returns 0 on success, or -1 on error. Note
+// that the font initialization failure would be non-fatal, as caller may not need to draw any text
+// at all. Caller can check the font initialization result via gr_sys_font() as needed.
 int gr_init();
+
+// Frees the allocated resources. The function is idempotent, and safe to be called if gr_init()
+// didn't finish successfully.
 void gr_exit();
 
 int gr_fb_width();
@@ -57,7 +63,8 @@
 void gr_flip();
 void gr_fb_blank(bool blank);
 
-void gr_clear();  // clear entire surface to current color
+// Clears entire surface to current color.
+void gr_clear();
 void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
 void gr_fill(int x1, int y1, int x2, int y2);
 
@@ -66,16 +73,16 @@
 const GRFont* gr_sys_font();
 int gr_init_font(const char* name, GRFont** dest);
 void gr_text(const GRFont* font, int x, int y, const char* s, bool bold);
-// Return -1 if font is nullptr.
+// Returns -1 if font is nullptr.
 int gr_measure(const GRFont* font, const char* s);
-// Return -1 if font is nullptr.
+// Returns -1 if font is nullptr.
 int gr_font_size(const GRFont* font, int* x, int* y);
 
 void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy);
-unsigned int gr_get_width(GRSurface* surface);
-unsigned int gr_get_height(GRSurface* surface);
+unsigned int gr_get_width(const GRSurface* surface);
+unsigned int gr_get_height(const GRSurface* surface);
 
-// Set rotation, flips gr_fb_width/height if 90 degree rotation difference
+// Sets rotation, flips gr_fb_width/height if 90 degree rotation difference
 void gr_rotate(GRRotation rotation);
 
 //
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 6f3a3a2..fe4f45e 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -100,7 +100,8 @@
 }
 
 static void RunBlockImageUpdate(bool is_verify, const PackageEntries& entries,
-                                const std::string& image_file, const std::string& result) {
+                                const std::string& image_file, const std::string& result,
+                                CauseCode cause_code = kNoCause) {
   CHECK(entries.find("transfer_list") != entries.end());
 
   // Build the update package.
@@ -124,7 +125,7 @@
   std::string script = is_verify ? "block_image_verify" : "block_image_update";
   script += R"((")" + image_file + R"(", package_extract_file("transfer_list"), ")" + new_data +
             R"(", "patch_data"))";
-  expect(result.c_str(), script.c_str(), kNoCause, &updater_info);
+  expect(result.c_str(), script.c_str(), cause_code, &updater_info);
 
   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
   CloseArchive(handle);
@@ -504,6 +505,24 @@
   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
 }
 
+TEST_F(UpdaterTest, block_image_update_parsing_error) {
+  std::vector<std::string> transfer_list{
+    // clang-format off
+    "4",
+    "2",
+    "0",
+    // clang-format on
+  };
+
+  PackageEntries entries{
+    { "new_data", "" },
+    { "patch_data", "" },
+    { "transfer_list", android::base::Join(transfer_list, '\n') },
+  };
+
+  RunBlockImageUpdate(false, entries, image_file_, "", kArgsParsingFailure);
+}
+
 TEST_F(UpdaterTest, block_image_update_patch_data) {
   std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
   std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index f2811bc..ff1d20a 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1091,9 +1091,8 @@
  * If the return value is 0, source blocks have expected content and the command can be performed.
  */
 static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet* tgt, size_t* src_blocks,
-                              bool onehash, bool* overlap) {
+                              bool onehash) {
   CHECK(src_blocks != nullptr);
-  CHECK(overlap != nullptr);
 
   if (params.cpos >= params.tokens.size()) {
     LOG(ERROR) << "missing source hash";
@@ -1135,15 +1134,16 @@
   }
 
   // Load source blocks.
-  if (LoadSourceBlocks(params, *tgt, src_blocks, overlap) == -1) {
+  bool overlap = false;
+  if (LoadSourceBlocks(params, *tgt, src_blocks, &overlap) == -1) {
     return -1;
   }
 
   if (VerifyBlocks(srchash, params.buffer, *src_blocks, true) == 0) {
-    // If source and target blocks overlap, stash the source blocks so we can
-    // resume from possible write errors. In verify mode, we can skip stashing
-    // because the source blocks won't be overwritten.
-    if (*overlap && params.canwrite) {
+    // If source and target blocks overlap, stash the source blocks so we can resume from possible
+    // write errors. In verify mode, we can skip stashing because the source blocks won't be
+    // overwritten.
+    if (overlap && params.canwrite) {
       LOG(INFO) << "stashing " << *src_blocks << " overlapping blocks to " << srchash;
 
       bool stash_exists = false;
@@ -1164,7 +1164,7 @@
     return 0;
   }
 
-  if (*overlap && LoadStash(params, srchash, true, &params.buffer, true) == 0) {
+  if (overlap && LoadStash(params, srchash, true, &params.buffer, true) == 0) {
     // Overlapping source blocks were previously stashed, command can proceed. We are recovering
     // from an interrupted command, so we don't know if the stash can safely be deleted after this
     // command.
@@ -1182,9 +1182,8 @@
 
 static int PerformCommandMove(CommandParameters& params) {
   size_t blocks = 0;
-  bool overlap = false;
   RangeSet tgt;
-  int status = LoadSrcTgtVersion3(params, &tgt, &blocks, true, &overlap);
+  int status = LoadSrcTgtVersion3(params, &tgt, &blocks, true);
 
   if (status == -1) {
     LOG(ERROR) << "failed to read blocks for move";
@@ -1382,8 +1381,7 @@
 
   RangeSet tgt;
   size_t blocks = 0;
-  bool overlap = false;
-  int status = LoadSrcTgtVersion3(params, &tgt, &blocks, false, &overlap);
+  int status = LoadSrcTgtVersion3(params, &tgt, &blocks, false);
 
   if (status == -1) {
     LOG(ERROR) << "failed to read blocks for diff";
@@ -1628,9 +1626,10 @@
     }
   }
 
+  static constexpr size_t kTransferListHeaderLines = 4;
   std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");
-  if (lines.size() < 2) {
-    ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]",
+  if (lines.size() < kTransferListHeaderLines) {
+    ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
                lines.size());
     return StringValue("");
   }
@@ -1654,12 +1653,6 @@
     return StringValue("t");
   }
 
-  if (lines.size() < 4) {
-    ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
-               lines.size());
-    return StringValue("");
-  }
-
   // Third line is how many stash entries are needed simultaneously.
   LOG(INFO) << "maximum stash entries " << lines[2];
 
@@ -1698,7 +1691,6 @@
 
   int rc = -1;
 
-  static constexpr size_t kTransferListHeaderLines = 4;
   // Subsequent lines are all individual transfer commands
   for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) {
     const std::string& line = lines[i];
diff --git a/updater_sample/Android.mk b/updater_sample/Android.mk
index 7662111..a5deee1 100644
--- a/updater_sample/Android.mk
+++ b/updater_sample/Android.mk
@@ -20,9 +20,8 @@
 LOCAL_PACKAGE_NAME := SystemUpdaterSample
 LOCAL_MODULE_TAGS := samples
 LOCAL_SDK_VERSION := system_current
-
-# TODO: enable proguard and use proguard.flags file
-LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/updater_sample/README.md b/updater_sample/README.md
index 8ec43d3..11b55eb 100644
--- a/updater_sample/README.md
+++ b/updater_sample/README.md
@@ -140,6 +140,9 @@
 no other update is running. The extra `key_value_pair_headers` will be
 included when fetching the payload.
 
+`key_value_pair_headers` argument also accepts properties other than HTTP Headers.
+List of allowed properties can be found in `system/update_engine/common/constants.cc`.
+
 ### UpdateEngine#cancel
 
 Cancel the ongoing update. The update could be running or suspended, but it
@@ -181,9 +184,8 @@
 - [x] Deferred switch slot demo
 - [x] Add UpdateManager; extract update logic from MainActivity
 - [x] Add Sample app update state (separate from update_engine status)
-- [-] Add smart update completion detection using onStatusUpdate
-- [ ] Add pause/resume demo
-- [ ] Add demo for passing NETWORK_ID to `UpdateEngine#applyPayload`
+- [x] Add smart update completion detection using onStatusUpdate
+- [x] Add pause/resume demo
 - [ ] Verify system partition checksum for package
 - [?] Add non-A/B updates demo
 
diff --git a/updater_sample/proguard.flags b/updater_sample/proguard.flags
new file mode 100644
index 0000000..5883608
--- /dev/null
+++ b/updater_sample/proguard.flags
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 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.
+
+# Keep, used in tests.
+-keep public class com.example.android.systemupdatersample.UpdateManager {
+   public int getUpdaterState();
+}
+
+# Keep, used in tests.
+-keep public class com.example.android.systemupdatersample.UpdateConfig {
+   public <init>(java.lang.String, java.lang.String, int);
+}
diff --git a/updater_sample/tests/Android.mk b/updater_sample/tests/Android.mk
index 9aec372..4157604 100644
--- a/updater_sample/tests/Android.mk
+++ b/updater_sample/tests/Android.mk
@@ -22,10 +22,10 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_JAVA_LIBRARIES := \
     android.test.base.stubs \
-    android.test.runner.stubs \
-    guava
+    android.test.runner.stubs
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test \
-    mockito-target-minus-junit4
+    mockito-target-minus-junit4 \
+    guava
 LOCAL_INSTRUMENTATION_FOR := SystemUpdaterSample
 LOCAL_PROGUARD_ENABLED := disabled
 
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 3ba84c1..0308693 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
@@ -65,7 +65,7 @@
         mTargetContext = InstrumentationRegistry.getTargetContext();
         mTestContext = InstrumentationRegistry.getContext();
 
-        mTestDir = mTargetContext.getFilesDir();
+        mTestDir = mTargetContext.getCacheDir();
         mPayloadSpecs = new PayloadSpecs();
     }
 
diff --git a/updater_sample/tools/gen_update_config.py b/updater_sample/tools/gen_update_config.py
index 7fb64f7..b43e49d 100755
--- a/updater_sample/tools/gen_update_config.py
+++ b/updater_sample/tools/gen_update_config.py
@@ -131,10 +131,10 @@
                         choices=ab_install_type_choices,
                         help='A/B update installation type')
     parser.add_argument('--ab_force_switch_slot',
-                        type=bool,
                         default=False,
-                        help='if set true device will boot to a new slot, otherwise user manually '
-                             'switches slot on the screen')
+                        action='store_true',
+                        help='if set device will boot to a new slot, otherwise user '
+                              'manually switches slot on the screen')
     parser.add_argument('package',
                         type=str,
                         help='OTA package zip file')